34
34
import org .springframework .context .SmartLifecycle ;
35
35
import org .springframework .core .task .SimpleAsyncTaskExecutor ;
36
36
import org .springframework .core .task .TaskExecutor ;
37
+ import org .springframework .data .redis .RedisConnectionFailureException ;
37
38
import org .springframework .data .redis .connection .Message ;
38
39
import org .springframework .data .redis .connection .MessageListener ;
39
40
import org .springframework .data .redis .connection .RedisConnection ;
65
66
*
66
67
*
67
68
* @author Costin Leau
69
+ * @author Way Joke
68
70
*/
69
71
public class RedisMessageListenerContainer implements InitializingBean , DisposableBean , BeanNameAware , SmartLifecycle {
70
72
@@ -116,8 +118,13 @@ public class RedisMessageListenerContainer implements InitializingBean, Disposab
116
118
private final SubscriptionTask subscriptionTask = new SubscriptionTask ();
117
119
118
120
private volatile RedisSerializer <String > serializer = new StringRedisSerializer ();
119
-
120
-
121
+
122
+ // will recovery redis listening after recovery tnterval setting
123
+ private long recoveryInterval = 3000L ;
124
+ // will recovery redis listening until reach the limit ( -1 will always try again)
125
+ private int multipleRetries = -1 ;
126
+ // the retried times
127
+ private int numberOfRetries = 0 ;
121
128
122
129
public void afterPropertiesSet () {
123
130
if (taskExecutor == null ) {
@@ -632,7 +639,45 @@ private void remove(MessageListener listener, Topic topic, ByteArrayWrapper hold
632
639
}
633
640
}
634
641
642
+ /**
643
+ * Handle subscription task exception, will recovery redis listening on RedisConnectionFailureExceptions.
644
+ * @param t Throwable exception
645
+ */
646
+ protected void refreshConnectionUntilSuccessful (Throwable t ) {
647
+ // we need to specifically deal with RedisConnectionFailureExceptions
648
+ // so we aren't attempting to reconnect if other types of failures occur.
649
+ if (t instanceof RedisConnectionFailureException ) {
650
+
651
+ if (multipleRetries > 0 && numberOfRetries > multipleRetries ) {
652
+ logger .error ("Retry count has reached the upper limit " + multipleRetries );
653
+ return ;
654
+ }
655
+
656
+ subscriptionExecutor .execute (new Runnable () {
635
657
658
+ public void run () {
659
+ if (multipleRetries > 0 ) {
660
+ numberOfRetries ++;
661
+ }
662
+ try {
663
+ stop ();
664
+ } catch (Throwable ex ) {
665
+ // as we know the stop will throw JedisConnectionException on jedis,
666
+ // catch Throwable will not need to import any jedis classes.
667
+ // The exception will be ignored.
668
+ }
669
+ logger .error ("Restarting subscription task after " + recoveryInterval + "ms." );
670
+ try {
671
+ Thread .sleep (recoveryInterval );
672
+ } catch (InterruptedException e ) {
673
+ return ;
674
+ }
675
+ start ();
676
+ }
677
+ });
678
+ }
679
+ }
680
+
636
681
/**
637
682
* Runnable used for Redis subscription. Implemented as a dedicated class to provide as many hints
638
683
* as possible to the underlying thread pool.
@@ -721,6 +766,9 @@ public void run() {
721
766
else {
722
767
connection .pSubscribe (new DispatchMessageListener (), unwrap (patternMapping .keySet ()));
723
768
}
769
+ } catch (Throwable t ) {
770
+ logger .error ("SubscriptionTask abort with exception:" , t );
771
+ refreshConnectionUntilSuccessful (t );
724
772
} finally {
725
773
// this block is executed once the subscription thread has ended, this may or may not mean
726
774
// the connection has been unsubscribed, depending on driver
@@ -870,4 +918,22 @@ public void run() {
870
918
});
871
919
}
872
920
}
921
+
922
+ /**
923
+ * Set the recovery interval value(ms), must be greater than zero
924
+ * @param recoveryInterval
925
+ */
926
+ public void setRecoveryInterval (long recoveryInterval ) {
927
+ if (recoveryInterval > 0 ) {
928
+ this .recoveryInterval = recoveryInterval ;
929
+ }
930
+ }
931
+
932
+ /**
933
+ * Set the multiple retries times, less than zero on behalf of the infinite.
934
+ * @param multipleRetries
935
+ */
936
+ public void setMultipleRetries (int multipleRetries ) {
937
+ this .multipleRetries = multipleRetries ;
938
+ }
873
939
}
0 commit comments