21
21
import java .util .concurrent .TimeUnit ;
22
22
import java .util .concurrent .locks .Lock ;
23
23
import java .util .concurrent .locks .ReentrantLock ;
24
+ import java .util .function .Supplier ;
25
+
26
+ import org .jspecify .annotations .Nullable ;
24
27
25
28
import org .springframework .beans .factory .DisposableBean ;
26
29
import org .springframework .context .ApplicationEventPublisher ;
59
62
*
60
63
* @since 4.3.1
61
64
*/
62
- public class LockRegistryLeaderInitiator implements SmartLifecycle , DisposableBean ,
63
- ApplicationEventPublisherAware {
65
+ public class LockRegistryLeaderInitiator implements SmartLifecycle , DisposableBean , ApplicationEventPublisherAware {
64
66
65
67
public static final long DEFAULT_HEART_BEAT_TIME = 500L ;
66
68
@@ -115,14 +117,15 @@ public String getRole() {
115
117
116
118
private boolean publishFailedEvents = false ;
117
119
118
- private LeaderSelector leaderSelector ;
120
+ private @ Nullable LeaderSelector leaderSelector ;
119
121
122
+ @ SuppressWarnings ("NullAway.Init" )
120
123
private ApplicationEventPublisher applicationEventPublisher ;
121
124
122
125
/**
123
126
* Leader event publisher if set.
124
127
*/
125
- private LeaderEventPublisher leaderEventPublisher ;
128
+ private @ Nullable LeaderEventPublisher leaderEventPublisher ;
126
129
127
130
/**
128
131
* @see SmartLifecycle
@@ -132,7 +135,7 @@ public String getRole() {
132
135
/**
133
136
* @see SmartLifecycle which is an extension of org.springframework.context.Phased
134
137
*/
135
- private int phase = Integer .MAX_VALUE - 1000 ; // NOSONAR magic number
138
+ private int phase = Integer .MAX_VALUE - 1000 ;
136
139
137
140
/**
138
141
* Time in milliseconds to wait in between attempts to acquire the lock, if it is not
@@ -155,7 +158,7 @@ public String getRole() {
155
158
* Future returned by submitting an {@link LeaderSelector} to
156
159
* {@link #taskExecutor}. This is used to cancel leadership.
157
160
*/
158
- private volatile Future <?> future ;
161
+ private volatile @ Nullable Future <?> future ;
159
162
160
163
/**
161
164
* Create a new leader initiator with the provided lock registry and a default
@@ -279,7 +282,7 @@ public void setPublishFailedEvents(boolean publishFailedEvents) {
279
282
public void start () {
280
283
this .lock .lock ();
281
284
try {
282
- if (this .leaderEventPublisher == null && this . applicationEventPublisher != null ) {
285
+ if (this .leaderEventPublisher == null ) {
283
286
this .leaderEventPublisher = new DefaultLeaderEventPublisher (this .applicationEventPublisher );
284
287
}
285
288
if (!this .running ) {
@@ -309,8 +312,9 @@ public void stop() {
309
312
try {
310
313
if (this .running ) {
311
314
this .running = false ;
312
- if (this .future != null ) {
313
- this .future .cancel (true );
315
+ Future <?> futureToCancel = this .future ;
316
+ if (futureToCancel != null ) {
317
+ futureToCancel .cancel (true );
314
318
}
315
319
this .future = null ;
316
320
LOGGER .debug (() -> "Stopped LeaderInitiator for " + getContext ());
@@ -334,7 +338,7 @@ protected class LeaderSelector implements Callable<Void> {
334
338
335
339
private final String lockKey ;
336
340
337
- private final LockContext context = new LockContext ();
341
+ private final LockContext context = new LockContext (this );
338
342
339
343
private volatile boolean locked = false ;
340
344
@@ -421,7 +425,7 @@ else if (acquired) {
421
425
}
422
426
}
423
427
424
- private boolean unlockAndHandleException (Exception ex ) { // NOSONAR
428
+ private boolean unlockAndHandleException (@ Nullable Exception ex ) {
425
429
if (this .locked ) {
426
430
this .locked = false ;
427
431
try {
@@ -450,18 +454,31 @@ private boolean unlockAndHandleException(Exception ex) { // NOSONAR
450
454
Thread .sleep (LockRegistryLeaderInitiator .this .busyWaitMillis );
451
455
}
452
456
catch (InterruptedException e1 ) {
453
- // Ignore interruption and let it be caught on the next cycle.
457
+ // Ignore the interruption and let it be caught on the next cycle.
454
458
Thread .currentThread ().interrupt ();
455
459
}
456
460
}
457
- LOGGER .debug (ex , () ->
458
- "Error acquiring the lock for " + this .context + ". " + (isRunning () ? "Retrying..." : "" ));
461
+ Supplier <CharSequence > debugMessage =
462
+ () -> "Error acquiring the lock for " + this .context + ". " + (isRunning () ? "Retrying..." : "" );
463
+ if (ex != null ) {
464
+ LOGGER .debug (ex , debugMessage );
465
+ }
466
+ else {
467
+ LOGGER .debug (debugMessage );
468
+ }
459
469
}
460
470
return false ;
461
471
}
462
472
463
- private void restartSelectorBecauseOfError (Exception ex ) {
464
- LOGGER .warn (ex , () -> "Restarting LeaderSelector for " + this .context + " because of error." );
473
+ private void restartSelectorBecauseOfError (@ Nullable Exception ex ) {
474
+ Supplier <CharSequence > warnMessage =
475
+ () -> "Restarting LeaderSelector for " + this .context + " because of error." ;
476
+ if (ex != null ) {
477
+ LOGGER .warn (ex , warnMessage );
478
+ }
479
+ else {
480
+ LOGGER .warn (warnMessage );
481
+ }
465
482
LockRegistryLeaderInitiator .this .future =
466
483
LockRegistryLeaderInitiator .this .taskExecutor .submit (
467
484
() -> {
@@ -523,18 +540,21 @@ private void publishFailedToAcquire() {
523
540
*/
524
541
private class LockContext implements Context {
525
542
526
- LockContext () {
543
+ private final LeaderSelector selector ;
544
+
545
+ LockContext (LeaderSelector leaderSelector ) {
546
+ this .selector = leaderSelector ;
527
547
}
528
548
529
549
@ Override
530
550
public boolean isLeader () {
531
- return LockRegistryLeaderInitiator . this .leaderSelector .isLeader ();
551
+ return this .selector .isLeader ();
532
552
}
533
553
534
554
@ Override
535
555
public void yield () {
536
556
LOGGER .debug (() -> "Yielding leadership from " + this );
537
- LockRegistryLeaderInitiator . this .leaderSelector .yielding = true ;
557
+ this .selector .yielding = true ;
538
558
}
539
559
540
560
@ Override
0 commit comments