Skip to content

Commit 7dc7170

Browse files
committed
Rename CredentialsRefreshService#needRefresh to isApproachingExpiration
[#167029587]
1 parent 2b6e5e1 commit 7dc7170

File tree

5 files changed

+66
-24
lines changed

5 files changed

+66
-24
lines changed

src/main/java/com/rabbitmq/client/impl/AMQConnection.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public void start()
349349
if (this.credentialsRefreshService == null) {
350350
throw new IllegalStateException("Credentials can expire, a credentials refresh service should be set");
351351
}
352-
if (this.credentialsRefreshService.needRefresh(credentialsProvider.getTimeBeforeExpiration())) {
352+
if (this.credentialsRefreshService.isApproachingExpiration(credentialsProvider.getTimeBeforeExpiration())) {
353353
credentialsProvider.refresh();
354354
username = credentialsProvider.getUsername();
355355
password = credentialsProvider.getPassword();

src/main/java/com/rabbitmq/client/impl/CredentialsRefreshService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,15 @@ public interface CredentialsRefreshService {
6363
void unregister(CredentialsProvider credentialsProvider, String registrationId);
6464

6565
/**
66-
* Provide a hint about whether credentials should be renewed.
66+
* Provide a hint about whether credentials should be renewed now or not before attempting to connect.
67+
* <p>
68+
* This can avoid a connection to use almost expired credentials if this connection
69+
* is created just before credentials are refreshed in the background, but does not
70+
* benefit from the refresh.
6771
*
6872
* @param timeBeforeExpiration
6973
* @return true if credentials should be renewed, false otherwise
7074
*/
71-
boolean needRefresh(Duration timeBeforeExpiration);
75+
boolean isApproachingExpiration(Duration timeBeforeExpiration);
7276

7377
}

src/main/java/com/rabbitmq/client/impl/DefaultCredentialsRefreshService.java

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,57 @@ public class DefaultCredentialsRefreshService implements CredentialsRefreshServi
4444

4545
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCredentialsRefreshService.class);
4646

47+
/**
48+
* Scheduler used to schedule credentials refresh.
49+
* <p>
50+
* Default is a single-threaded scheduler, which should be enough for most scenarios, assuming
51+
* that credentials expire after a few minutes or hours. This default scheduler
52+
* is automatically disposed of when the {@link DefaultCredentialsRefreshService} is closed.
53+
* <p>
54+
* If an external scheduler is passed in, it is the developer's responsibility to
55+
* close it.
56+
*/
4757
private final ScheduledExecutorService scheduler;
4858

4959
private final ConcurrentMap<CredentialsProvider, CredentialsProviderState> credentialsProviderStates = new ConcurrentHashMap<>();
5060

5161
private final boolean privateScheduler;
5262

63+
/**
64+
* Strategy to schedule credentials refresh after credentials retrieval.
65+
* <p>
66+
* Typical strategies schedule refresh after a ratio of the time before expiration
67+
* (e.g. 80 % of the time before expiration) or after a fixed time before
68+
* expiration (e.g. 20 seconds before credentials expire).
69+
*
70+
* @see #ratioRefreshDelayStrategy(double)
71+
* @see #fixedDelayBeforeExpirationRefreshDelayStrategy(Duration)
72+
*/
5373
private final Function<Duration, Duration> refreshDelayStrategy;
5474

55-
private final Function<Duration, Boolean> needRefreshStrategy;
75+
/**
76+
* Strategy to provide a hint about whether credentials should be renewed now or not before attempting to connect.
77+
* <p>
78+
* This can avoid a connection to use almost expired credentials if this connection
79+
* is created just before credentials are refreshed in the background, but does not
80+
* benefit from the refresh.
81+
* <p>
82+
* Note setting such a strategy may require knowledge of the credentials validity and must be consistent
83+
* with the {@link #refreshDelayStrategy} chosen. For example, for a validity of 60 minutes and
84+
* a {@link #refreshDelayStrategy} that instructs to refresh 10 minutes before credentials expire, this
85+
* strategy could hint that credentials that expire in 11 minutes or less (1 minute before a refresh is actually
86+
* scheduled) should be refreshed, which would trigger an early refresh.
87+
* <p>
88+
* The default strategy always return false.
89+
*/
90+
private final Function<Duration, Boolean> approachingExpirationStrategy;
5691

57-
public DefaultCredentialsRefreshService(ScheduledExecutorService scheduler, Function<Duration, Duration> refreshDelayStrategy, Function<Duration, Boolean> needRefreshStrategy) {
92+
public DefaultCredentialsRefreshService(ScheduledExecutorService scheduler, Function<Duration, Duration> refreshDelayStrategy, Function<Duration, Boolean> approachingExpirationStrategy) {
93+
if (refreshDelayStrategy == null) {
94+
throw new IllegalArgumentException("Refresh delay strategy can not be null");
95+
}
5896
this.refreshDelayStrategy = refreshDelayStrategy;
59-
this.needRefreshStrategy = needRefreshStrategy;
97+
this.approachingExpirationStrategy = approachingExpirationStrategy == null ? duration -> false : approachingExpirationStrategy;
6098
if (scheduler == null) {
6199
this.scheduler = Executors.newScheduledThreadPool(1);
62100
privateScheduler = true;
@@ -69,8 +107,8 @@ public DefaultCredentialsRefreshService(ScheduledExecutorService scheduler, Func
69107
/**
70108
* Delay before refresh is a ratio of the time before expiration.
71109
* <p>
72-
* E.g. if time before expiration is 60 seconds and specified ratio is 0.8, refresh will
73-
* be scheduled in 60 x 0.8 = 48 seconds.
110+
* E.g. if time before expiration is 60 minutes and specified ratio is 0.8, refresh will
111+
* be scheduled in 60 x 0.8 = 48 minutes.
74112
*
75113
* @param ratio
76114
* @return the delay before refreshing
@@ -82,8 +120,8 @@ public static Function<Duration, Duration> ratioRefreshDelayStrategy(double rati
82120
/**
83121
* Delay before refresh is <code>time before expiration - specified duration</code>.
84122
* <p>
85-
* E.g. if time before expiration is 60 seconds and specified duration is 20 seconds, refresh will
86-
* be scheduled in 60 - 20 = 40 seconds.
123+
* E.g. if time before expiration is 60 minutes and specified duration is 10 minutes, refresh will
124+
* be scheduled in 60 - 10 = 50 minutes.
87125
*
88126
* @param duration
89127
* @return the delay before refreshing
@@ -98,8 +136,8 @@ public static Function<Duration, Duration> fixedDelayBeforeExpirationRefreshDela
98136
* @param limitBeforeExpiration
99137
* @return true if credentials should be refreshed, false otherwise
100138
*/
101-
public static Function<Duration, Boolean> fixedTimeNeedRefreshStrategy(Duration limitBeforeExpiration) {
102-
return new FixedTimeNeedRefreshStrategy(limitBeforeExpiration.toMillis());
139+
public static Function<Duration, Boolean> fixedTimeApproachingExpirationStrategy(Duration limitBeforeExpiration) {
140+
return new FixedTimeApproachingExpirationStrategy(limitBeforeExpiration.toMillis());
103141
}
104142

105143
private static Runnable refresh(ScheduledExecutorService scheduler, CredentialsProviderState credentialsProviderState,
@@ -157,8 +195,8 @@ public void unregister(CredentialsProvider credentialsProvider, String registrat
157195
}
158196

159197
@Override
160-
public boolean needRefresh(Duration timeBeforeExpiration) {
161-
return this.needRefreshStrategy.apply(timeBeforeExpiration);
198+
public boolean isApproachingExpiration(Duration timeBeforeExpiration) {
199+
return this.approachingExpirationStrategy.apply(timeBeforeExpiration);
162200
}
163201

164202
public void close() {
@@ -167,11 +205,11 @@ public void close() {
167205
}
168206
}
169207

170-
private static class FixedTimeNeedRefreshStrategy implements Function<Duration, Boolean> {
208+
private static class FixedTimeApproachingExpirationStrategy implements Function<Duration, Boolean> {
171209

172210
private final long limitBeforeExpiration;
173211

174-
private FixedTimeNeedRefreshStrategy(long limitBeforeExpiration) {
212+
private FixedTimeApproachingExpirationStrategy(long limitBeforeExpiration) {
175213
this.limitBeforeExpiration = limitBeforeExpiration;
176214
}
177215

@@ -340,7 +378,7 @@ public static class DefaultCredentialsRefreshServiceBuilder {
340378

341379
private Function<Duration, Duration> refreshDelayStrategy = ratioRefreshDelayStrategy(0.8);
342380

343-
private Function<Duration, Boolean> needRefreshStrategy = ttl -> false;
381+
private Function<Duration, Boolean> approachingExpirationStrategy = ttl -> false;
344382

345383
public DefaultCredentialsRefreshServiceBuilder scheduler(ScheduledThreadPoolExecutor scheduler) {
346384
this.scheduler = scheduler;
@@ -352,13 +390,13 @@ public DefaultCredentialsRefreshServiceBuilder refreshDelayStrategy(Function<Dur
352390
return this;
353391
}
354392

355-
public DefaultCredentialsRefreshServiceBuilder needRefreshStrategy(Function<Duration, Boolean> needRefreshStrategy) {
356-
this.needRefreshStrategy = needRefreshStrategy;
393+
public DefaultCredentialsRefreshServiceBuilder approachingExpirationStrategy(Function<Duration, Boolean> approachingExpirationStrategy) {
394+
this.approachingExpirationStrategy = approachingExpirationStrategy;
357395
return this;
358396
}
359397

360398
public DefaultCredentialsRefreshService build() {
361-
return new DefaultCredentialsRefreshService(scheduler, refreshDelayStrategy, needRefreshStrategy);
399+
return new DefaultCredentialsRefreshService(scheduler, refreshDelayStrategy, approachingExpirationStrategy);
362400
}
363401

364402
}

src/test/java/com/rabbitmq/client/impl/DefaultCredentialsRefreshServiceTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import java.util.stream.IntStream;
3434

3535
import static com.rabbitmq.client.impl.DefaultCredentialsRefreshService.fixedDelayBeforeExpirationRefreshDelayStrategy;
36-
import static com.rabbitmq.client.impl.DefaultCredentialsRefreshService.fixedTimeNeedRefreshStrategy;
36+
import static com.rabbitmq.client.impl.DefaultCredentialsRefreshService.fixedTimeApproachingExpirationStrategy;
3737
import static java.time.Duration.ofSeconds;
3838
import static org.assertj.core.api.Assertions.assertThat;
3939
import static org.mockito.Mockito.*;
@@ -232,8 +232,8 @@ public void fixedDelayBeforeExpirationRefreshDelayStrategyTest() {
232232
}
233233

234234
@Test
235-
public void fixedTimeNeedRefreshStrategyTest() {
236-
Function<Duration, Boolean> refreshStrategy = fixedTimeNeedRefreshStrategy(ofSeconds(20));
235+
public void fixedTimeApproachingExpirationStrategyTest() {
236+
Function<Duration, Boolean> refreshStrategy = fixedTimeApproachingExpirationStrategy(ofSeconds(20));
237237
assertThat(refreshStrategy.apply(ofSeconds(60))).isFalse();
238238
assertThat(refreshStrategy.apply(ofSeconds(20))).isTrue();
239239
assertThat(refreshStrategy.apply(ofSeconds(19))).isTrue();

src/test/java/com/rabbitmq/client/test/RefreshCredentialsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ protected Duration timeBeforeExpiration(TestToken token) {
7676
cf.setCredentialsProvider(provider);
7777
refreshService = new DefaultCredentialsRefreshService.DefaultCredentialsRefreshServiceBuilder()
7878
.refreshDelayStrategy(DefaultCredentialsRefreshService.fixedDelayBeforeExpirationRefreshDelayStrategy(Duration.ofSeconds(1)))
79-
.needRefreshStrategy(expiration -> false)
79+
.approachingExpirationStrategy(expiration -> false)
8080
.build();
8181
cf.setCredentialsRefreshService(refreshService);
8282

0 commit comments

Comments
 (0)