@Override
    public void afterCompletion(int status) {

      try {
        switch (status) {
          case TransactionSynchronization.STATUS_COMMITTED:
            connection.exec();
            break;

          case TransactionSynchronization.STATUS_ROLLED_BACK:
          case TransactionSynchronization.STATUS_UNKNOWN:
          default:
            connection.discard();
        }
      } finally {

        if (log.isDebugEnabled()) {
          log.debug("Closing bound connection after transaction completed with " + status);
        }

        connHolder.setTransactionSyncronisationActive(false);
        connection.close();
        TransactionSynchronizationManager.unbindResource(factory);
      }
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
        throws Throwable {

      RedisCommand commandToExecute = RedisCommand.failsafeCommandLookup(method.getName());

      if (isPotentiallyThreadBoundCommand(commandToExecute)) {

        if (log.isDebugEnabled()) {
          log.debug(String.format("Invoke '%s' on bound conneciton", method.getName()));
        }

        return invoke(method, obj, args);
      }

      if (log.isDebugEnabled()) {
        log.debug(String.format("Invoke '%s' on unbound conneciton", method.getName()));
      }

      RedisConnection connection = factory.getConnection();

      try {
        return invoke(method, connection, args);
      } finally {
        // properly close the unbound connection after executing command
        if (!connection.isClosed()) {
          connection.close();
        }
      }
    }
 private void processInPipeline(PipelineCallback callback) {
   RedisConnection connection =
       RedisConnectionUtils.bindConnection(redisTemplate.getConnectionFactory());
   try {
     connection.openPipeline();
     callback.process();
   } finally {
     connection.closePipeline();
     RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
   }
 }
  private static void potentiallyRegisterTransactionSynchronisation(
      RedisConnectionHolder connHolder, final RedisConnectionFactory factory) {

    if (isActualNonReadonlyTransactionActive()) {

      if (!connHolder.isTransactionSyncronisationActive()) {
        connHolder.setTransactionSyncronisationActive(true);

        RedisConnection conn = connHolder.getConnection();
        conn.multi();

        TransactionSynchronizationManager.registerSynchronization(
            new RedisTransactionSynchronizer(connHolder, conn, factory));
      }
    }
  }
  /**
   * Unbinds and closes the connection (if any) associated with the given factory.
   *
   * @param factory Redis factory
   */
  public static void unbindConnection(RedisConnectionFactory factory) {

    RedisConnectionHolder connHolder =
        (RedisConnectionHolder) TransactionSynchronizationManager.unbindResourceIfPossible(factory);

    if (connHolder != null) {
      if (connHolder.isTransactionSyncronisationActive()) {
        if (log.isDebugEnabled()) {
          log.debug("Redis Connection will be closed when outer transaction finished.");
        }
      } else {
        if (log.isDebugEnabled()) {
          log.debug("Closing bound connection.");
        }
        RedisConnection connection = connHolder.getConnection();
        connection.close();
      }
    }
  }
  /**
   * 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
   */
  public static void releaseConnection(RedisConnection conn, RedisConnectionFactory factory) {

    if (conn == null) {
      return;
    }

    RedisConnectionHolder connHolder =
        (RedisConnectionHolder) TransactionSynchronizationManager.getResource(factory);

    if (connHolder != null && connHolder.isTransactionSyncronisationActive()) {
      if (log.isDebugEnabled()) {
        log.debug("Redis Connection will be closed when transaction finished.");
      }
      return;
    }

    // Only release non-transactional/non-bound connections.
    if (!isConnectionTransactional(conn, factory)) {
      if (log.isDebugEnabled()) {
        log.debug("Closing Redis Connection");
      }
      conn.close();
    }
  }
 public static Version getRedisVersion(RedisConnection connection) {
   return parseVersion((String) connection.info().get("redis_version"));
 }