DATAREDIS-988 - Consider transaction participation when releasing connections.

We now consider RedisTemplate's enableTransactionSupport configuration when releasing connections. Previously, we released bound connections when being in a read-only transaction regardless the configuration in RedisTemplate. This broke session callbacks that expected to remain on the same connection all but the first command were executed on a different connection.

Releasing a connection now no longer unbinds a connection if transaction support is disabled.

Original Pull Request: #453
This commit is contained in:
Mark Paluch
2019-06-03 11:05:05 +02:00
committed by Christoph Strobl
parent da1de92645
commit ae2042b1eb
3 changed files with 98 additions and 6 deletions

View File

@@ -187,8 +187,24 @@ public abstract class RedisConnectionUtils {
*
* @param conn the Redis connection to close.
* @param factory the Redis factory that the connection was created with.
* @deprecated since 2.1.9, use {@link #releaseConnection(RedisConnection, RedisConnectionFactory, boolean)}
*/
@Deprecated
public static void releaseConnection(@Nullable RedisConnection conn, RedisConnectionFactory factory) {
releaseConnection(conn, factory, false);
}
/**
* Closes the given connection, created via the given factory if not managed externally (i.e. not bound to the
* thread).
*
* @param conn the Redis connection to close.
* @param factory the Redis factory that the connection was created with.
* @param enableTransactionSupport whether transaction support is enabled.
* @since 2.1.9
*/
public static void releaseConnection(@Nullable RedisConnection conn, RedisConnectionFactory factory,
boolean enableTransactionSupport) {
if (conn == null) {
return;
@@ -203,11 +219,25 @@ public abstract class RedisConnectionUtils {
return;
}
// release transactional/read-only and non-transactional/non-bound connections.
// transactional connections for read-only transactions get no synchronizer registered
if (isConnectionTransactional(conn, factory) && TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
unbindConnection(factory);
} else if (!isConnectionTransactional(conn, factory)) {
if (isConnectionTransactional(conn, factory)) {
// release transactional/read-only and non-transactional/non-bound connections.
// transactional connections for read-only transactions get no synchronizer registered
if (enableTransactionSupport && TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
if (log.isDebugEnabled()) {
log.debug("Unbinding Redis Connection");
}
unbindConnection(factory);
} else {
// Not participating in transaction management.
// Connection could have been attached via session callback.
if (log.isDebugEnabled()) {
log.debug("Leaving bound Redis Connection attached");
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Closing Redis Connection");
}

View File

@@ -234,7 +234,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
RedisConnectionUtils.releaseConnection(conn, factory, enableTransactionSupport);
}
}