22
22
import static io .lettuce .core .event .cluster .AdaptiveRefreshTriggeredEvent .*;
23
23
24
24
import java .time .Duration ;
25
- import java .util .concurrent .CompletableFuture ;
26
25
import java .util .concurrent .CompletionStage ;
27
26
import java .util .concurrent .TimeUnit ;
28
27
import java .util .concurrent .atomic .AtomicBoolean ;
29
28
import java .util .concurrent .atomic .AtomicReference ;
29
+ import java .util .concurrent .locks .Condition ;
30
+ import java .util .concurrent .locks .ReentrantLock ;
30
31
import java .util .function .Supplier ;
31
32
32
33
import io .lettuce .core .ClientOptions ;
@@ -65,6 +66,10 @@ class ClusterTopologyRefreshScheduler implements Runnable, ClusterEventListener
65
66
66
67
private final EventExecutorGroup genericWorkerPool ;
67
68
69
+ private static final ReentrantLock refreshLock = new ReentrantLock ();
70
+
71
+ private static final Condition refreshComplete = refreshLock .newCondition ();
72
+
68
73
ClusterTopologyRefreshScheduler (Supplier <ClusterClientOptions > clientOptions , Supplier <Partitions > partitions ,
69
74
Supplier <CompletionStage <?>> refreshTopology , ClientResources clientResources ) {
70
75
@@ -94,33 +99,33 @@ protected void activateTopologyRefreshIfNeeded() {
94
99
/**
95
100
* Suspend (cancel) periodic topology refresh.
96
101
*/
97
- public CompletableFuture <Void > suspendTopologyRefresh () {
98
- CompletableFuture <Void > completionFuture = new CompletableFuture <>();
102
+ public void suspendTopologyRefresh () {
99
103
100
104
if (clusterTopologyRefreshActivated .compareAndSet (true , false )) {
105
+
101
106
ScheduledFuture <?> scheduledFuture = clusterTopologyRefreshFuture .get ();
102
107
103
108
try {
104
- if (scheduledFuture != null ) {
105
- scheduledFuture .cancel (false );
106
- clusterTopologyRefreshFuture .set (null );
107
- }
108
- completionFuture .complete (null );
109
+ scheduledFuture .cancel (false );
110
+ clusterTopologyRefreshFuture .set (null );
109
111
} catch (Exception e ) {
110
112
logger .debug ("Could not cancel Cluster topology refresh" , e );
111
- completionFuture .completeExceptionally (e );
112
113
}
113
- } else {
114
- completionFuture .complete (null );
115
114
}
116
-
117
- return completionFuture ;
118
115
}
119
116
120
117
public boolean isTopologyRefreshInProgress () {
121
118
return clusterTopologyRefreshTask .get ();
122
119
}
123
120
121
+ public ReentrantLock getRefreshLock () {
122
+ return refreshLock ;
123
+ }
124
+
125
+ public Condition getRefreshComplete () {
126
+ return refreshComplete ;
127
+ }
128
+
124
129
@ Override
125
130
public void run () {
126
131
@@ -332,13 +337,18 @@ private static class ClusterTopologyRefreshTask extends AtomicBoolean implements
332
337
333
338
public void run () {
334
339
335
- if (compareAndSet (false , true )) {
336
- doRun ();
337
- return ;
338
- }
340
+ refreshLock .lock ();
341
+ try {
342
+ if (compareAndSet (false , true )) {
343
+ doRun ();
344
+ return ;
345
+ }
339
346
340
- if (logger .isDebugEnabled ()) {
341
- logger .debug ("ClusterTopologyRefreshTask already in progress" );
347
+ if (logger .isDebugEnabled ()) {
348
+ logger .debug ("ClusterTopologyRefreshTask already in progress" );
349
+ }
350
+ } finally {
351
+ refreshLock .unlock ();
342
352
}
343
353
}
344
354
@@ -354,7 +364,13 @@ void doRun() {
354
364
logger .warn ("Cannot refresh Redis Cluster topology" , throwable );
355
365
}
356
366
357
- set (false );
367
+ refreshLock .lock ();
368
+ try {
369
+ set (false );
370
+ refreshComplete .signalAll ();
371
+ } finally {
372
+ refreshLock .unlock ();
373
+ }
358
374
});
359
375
} catch (Exception e ) {
360
376
logger .warn ("Cannot refresh Redis Cluster topology" , e );
0 commit comments