@@ -370,7 +370,7 @@ private void lazyListen() {
370
370
State state = this .state .get ();
371
371
372
372
CompletableFuture <Void > futureToAwait = state .isPrepareListening () ? containerListenFuture
373
- : lazyListen (this .backOff .start ());
373
+ : lazyListen (new InitialBackoffExecution ( this .backOff .start () ));
374
374
375
375
try {
376
376
futureToAwait .get (getMaxSubscriptionRegistrationWaitingTime (), TimeUnit .MILLISECONDS );
@@ -531,8 +531,7 @@ private void awaitRegistrationTime(CompletableFuture<Void> future) {
531
531
future .get (getMaxSubscriptionRegistrationWaitingTime (), TimeUnit .MILLISECONDS );
532
532
} catch (InterruptedException ex ) {
533
533
Thread .currentThread ().interrupt ();
534
- } catch (ExecutionException | TimeoutException ignore ) {
535
- }
534
+ } catch (ExecutionException | TimeoutException ignore ) {}
536
535
}
537
536
538
537
@ Override
@@ -876,7 +875,7 @@ protected void handleSubscriptionException(CompletableFuture<Void> future, BackO
876
875
877
876
if (recoveryInterval != BackOffExecution .STOP ) {
878
877
String message = String .format ("Connection failure occurred: %s; Restarting subscription task after %s ms" ,
879
- cause , recoveryInterval );
878
+ cause , recoveryInterval );
880
879
logger .error (message , cause );
881
880
}
882
881
@@ -885,8 +884,13 @@ protected void handleSubscriptionException(CompletableFuture<Void> future, BackO
885
884
886
885
Runnable recoveryFunction = () -> {
887
886
888
- CompletableFuture <Void > lazyListen = lazyListen (backOffExecution );
889
- lazyListen .whenComplete (propagate (future ));
887
+ CompletableFuture <Void > lazyListen = lazyListen (new RecoveryBackoffExecution (backOffExecution ));
888
+ lazyListen .whenComplete (propagate (future )).thenRun (() -> {
889
+
890
+ if (backOffExecution instanceof RecoveryAfterSubscriptionBackoffExecution ) {
891
+ logger .info ("Subscription(s) recovered" );
892
+ }
893
+ });
890
894
};
891
895
892
896
if (potentiallyRecover (loggingBackOffExecution , recoveryFunction )) {
@@ -980,7 +984,7 @@ private boolean hasTopics() {
980
984
private Subscriber getRequiredSubscriber () {
981
985
982
986
Assert .state (this .subscriber != null ,
983
- "Subscriber not created; Configure RedisConnectionFactory to create a Subscriber" );
987
+ "Subscriber not created; Configure RedisConnectionFactory to create a Subscriber. Make sure that afterPropertiesSet() has been called " );
984
988
985
989
return this .subscriber ;
986
990
}
@@ -1018,6 +1022,54 @@ private void logTrace(Supplier<String> message) {
1018
1022
}
1019
1023
}
1020
1024
1025
+ BackOffExecution nextBackoffExecution (BackOffExecution backOffExecution , boolean subscribed ) {
1026
+
1027
+ if (subscribed ) {
1028
+ return new RecoveryAfterSubscriptionBackoffExecution (backOff .start ());
1029
+ }
1030
+
1031
+ return backOffExecution ;
1032
+ }
1033
+
1034
+ /**
1035
+ * Marker for an initial backoff.
1036
+ *
1037
+ * @param delegate
1038
+ */
1039
+ record InitialBackoffExecution (BackOffExecution delegate ) implements BackOffExecution {
1040
+
1041
+ @ Override
1042
+ public long nextBackOff () {
1043
+ return delegate .nextBackOff ();
1044
+ }
1045
+ }
1046
+
1047
+ /**
1048
+ * Marker for a recovery after a subscription has been active previously.
1049
+ *
1050
+ * @param delegate
1051
+ */
1052
+ record RecoveryAfterSubscriptionBackoffExecution (BackOffExecution delegate ) implements BackOffExecution {
1053
+
1054
+ @ Override
1055
+ public long nextBackOff () {
1056
+ return delegate .nextBackOff ();
1057
+ }
1058
+ }
1059
+
1060
+ /**
1061
+ * Marker for a recovery execution.
1062
+ *
1063
+ * @param delegate
1064
+ */
1065
+ record RecoveryBackoffExecution (BackOffExecution delegate ) implements BackOffExecution {
1066
+
1067
+ @ Override
1068
+ public long nextBackOff () {
1069
+ return delegate .nextBackOff ();
1070
+ }
1071
+ }
1072
+
1021
1073
/**
1022
1074
* Represents an operation that accepts three input arguments {@link SubscriptionListener},
1023
1075
* {@code channel or pattern}, and {@code count} and returns no result.
@@ -1191,18 +1243,23 @@ public CompletableFuture<Void> initialize(BackOffExecution backOffExecution, Col
1191
1243
if (connection .isSubscribed ()) {
1192
1244
1193
1245
initFuture .completeExceptionally (
1194
- new IllegalStateException ("Retrieved connection is already subscribed; aborting listening" ));
1246
+ new IllegalStateException ("Retrieved connection is already subscribed; aborting listening" ));
1195
1247
1196
1248
return initFuture ;
1197
1249
}
1198
1250
1199
1251
try {
1200
1252
eventuallyPerformSubscription (connection , backOffExecution , initFuture , patterns , channels );
1201
1253
} catch (Throwable t ) {
1202
- handleSubscriptionException (initFuture , backOffExecution , t );
1254
+ handleSubscriptionException (initFuture , nextBackoffExecution (backOffExecution , connection .isSubscribed ()),
1255
+ t );
1203
1256
}
1204
1257
} catch (RuntimeException ex ) {
1205
- initFuture .completeExceptionally (ex );
1258
+ if (backOffExecution instanceof InitialBackoffExecution ) {
1259
+ initFuture .completeExceptionally (ex );
1260
+ } else {
1261
+ handleSubscriptionException (initFuture , backOffExecution , ex );
1262
+ }
1206
1263
}
1207
1264
1208
1265
return initFuture ;
@@ -1215,8 +1272,9 @@ public CompletableFuture<Void> initialize(BackOffExecution backOffExecution, Col
1215
1272
void eventuallyPerformSubscription (RedisConnection connection , BackOffExecution backOffExecution ,
1216
1273
CompletableFuture <Void > subscriptionDone , Collection <byte []> patterns , Collection <byte []> channels ) {
1217
1274
1218
- addSynchronization (new SynchronizingMessageListener .SubscriptionSynchronization (patterns , channels ,
1219
- () -> subscriptionDone .complete (null )));
1275
+ addSynchronization (new SynchronizingMessageListener .SubscriptionSynchronization (patterns , channels , () -> {
1276
+ subscriptionDone .complete (null );
1277
+ }));
1220
1278
1221
1279
doSubscribe (connection , patterns , channels );
1222
1280
}
@@ -1381,7 +1439,10 @@ private void doWithSubscription(byte[][] data, BiConsumer<Subscription, byte[][]
1381
1439
}
1382
1440
1383
1441
private void doInLock (Runnable runner ) {
1384
- doInLock (() -> { runner .run (); return null ; });
1442
+ doInLock (() -> {
1443
+ runner .run ();
1444
+ return null ;
1445
+ });
1385
1446
}
1386
1447
1387
1448
private <T > T doInLock (Supplier <T > supplier ) {
@@ -1432,7 +1493,7 @@ protected void eventuallyPerformSubscription(RedisConnection connection, BackOff
1432
1493
try {
1433
1494
subscribeChannel (channels .toArray (new byte [0 ][]));
1434
1495
} catch (Exception ex ) {
1435
- handleSubscriptionException (subscriptionDone , backOffExecution , ex );
1496
+ handleSubscriptionException (subscriptionDone , nextBackoffExecution ( backOffExecution , true ) , ex );
1436
1497
}
1437
1498
}));
1438
1499
} else {
@@ -1449,7 +1510,8 @@ protected void eventuallyPerformSubscription(RedisConnection connection, BackOff
1449
1510
closeConnection ();
1450
1511
unsubscribeFuture .complete (null );
1451
1512
} catch (Throwable cause ) {
1452
- handleSubscriptionException (subscriptionDone , backOffExecution , cause );
1513
+ handleSubscriptionException (subscriptionDone ,
1514
+ nextBackoffExecution (backOffExecution , connection .isSubscribed ()), cause );
1453
1515
}
1454
1516
});
1455
1517
}
0 commit comments