Polishing.
Allow Jedis to exist pub/sub loop gracefully. Await unsubscribe. Reduce retry backoff to allow from broken connection recovery. Do not use pooling to avoid using broken connections. See #2256
This commit is contained in:
@@ -265,7 +265,7 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
}
|
||||
|
||||
try {
|
||||
futureToAwait.get(getMaxSubscriptionRegistrationWaitingTime(), TimeUnit.SECONDS);
|
||||
futureToAwait.get(getMaxSubscriptionRegistrationWaitingTime(), TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (ExecutionException e) {
|
||||
@@ -391,15 +391,13 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
listenFuture.join();
|
||||
} catch (Exception e) {
|
||||
// ignore, just await completion here.
|
||||
}
|
||||
awaitRegistrationTime(listenFuture);
|
||||
|
||||
if (this.state.compareAndSet(state, State.prepareUnsubscribe())) {
|
||||
|
||||
getRequiredSubscriber().cancel();
|
||||
getRequiredSubscriber().unsubscribeAll();
|
||||
|
||||
awaitRegistrationTime(this.unsubscribeFuture);
|
||||
|
||||
this.state.set(State.notListening());
|
||||
|
||||
@@ -416,6 +414,16 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
}
|
||||
}
|
||||
|
||||
private void awaitRegistrationTime(CompletableFuture<Void> future) {
|
||||
try {
|
||||
future.get(getMaxSubscriptionRegistrationWaitingTime(), TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
} catch (ExecutionException | TimeoutException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return this.started.get();
|
||||
@@ -876,7 +884,8 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
long recoveryInterval = backOffExecution.nextBackOff();
|
||||
|
||||
if (recoveryInterval != BackOffExecution.STOP) {
|
||||
logger.error(String.format("Connection failure occurred: %s. Restarting subscription task after %s ms.", ex, recoveryInterval));
|
||||
logger.error(String.format("Connection failure occurred: %s. Restarting subscription task after %s ms.", ex,
|
||||
recoveryInterval), ex);
|
||||
}
|
||||
|
||||
return recoveryInterval;
|
||||
@@ -897,7 +906,9 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
return;
|
||||
}
|
||||
|
||||
logger.error("SubscriptionTask aborted with exception:", ex);
|
||||
if (isRunning()) { // log only if the container is still running to prevent close errors from logging
|
||||
logger.error("SubscriptionTask aborted with exception:", ex);
|
||||
}
|
||||
future.completeExceptionally(ex);
|
||||
}
|
||||
|
||||
@@ -1216,6 +1227,26 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
this.synchronizingMessageListener.addSynchronization(synchronizer);
|
||||
}
|
||||
|
||||
public void unsubscribeAll() {
|
||||
|
||||
synchronized (localMonitor) {
|
||||
|
||||
RedisConnection connection = this.connection;
|
||||
if (connection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
doUnsubscribe(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void doUnsubscribe(RedisConnection connection) {
|
||||
closeSubscription(connection);
|
||||
closeConnection();
|
||||
|
||||
unsubscribeFuture.complete(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel all subscriptions and close the connection.
|
||||
*/
|
||||
@@ -1228,26 +1259,34 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
return;
|
||||
}
|
||||
|
||||
doCancel(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void doCancel(RedisConnection connection) {
|
||||
closeSubscription(connection);
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void closeSubscription(RedisConnection connection) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Cancelling Redis subscription...");
|
||||
}
|
||||
|
||||
Subscription sub = connection.getSubscription();
|
||||
|
||||
if (sub != null) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Cancelling Redis subscription...");
|
||||
logger.trace("Unsubscribing from all channels");
|
||||
}
|
||||
|
||||
Subscription sub = connection.getSubscription();
|
||||
|
||||
if (sub != null) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Unsubscribing from all channels");
|
||||
}
|
||||
|
||||
try {
|
||||
sub.close();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to unsubscribe from subscriptions", e);
|
||||
}
|
||||
try {
|
||||
sub.close();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to unsubscribe from subscriptions", e);
|
||||
}
|
||||
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1324,6 +1363,7 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1341,6 +1381,11 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doUnsubscribe(RedisConnection connection) {
|
||||
closeSubscription(connection); // connection will be closed after exiting the doSubscribe method
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void eventuallyPerformSubscription(RedisConnection connection, BackOffExecution backOffExecution,
|
||||
CompletableFuture<Void> subscriptionDone, Collection<byte[]> patterns, Collection<byte[]> channels) {
|
||||
@@ -1369,6 +1414,8 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
|
||||
|
||||
try {
|
||||
doSubscribe(connection, patterns, initiallySubscribeToChannels);
|
||||
closeConnection();
|
||||
unsubscribeFuture.complete(null);
|
||||
} catch (Throwable t) {
|
||||
handleSubscriptionException(subscriptionDone, backOffExecution, t);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user