15
15
16
16
package software .amazon .awssdk .utils .cache ;
17
17
18
- import static java .time .temporal .ChronoUnit .HOURS ;
19
- import static java .time .temporal .ChronoUnit .MINUTES ;
20
-
21
18
import java .time .Duration ;
22
19
import java .time .Instant ;
23
- import java .util .Optional ;
24
- import java .util .Random ;
25
20
import java .util .concurrent .ScheduledFuture ;
26
21
import java .util .concurrent .ScheduledThreadPoolExecutor ;
27
22
import java .util .concurrent .Semaphore ;
@@ -57,11 +52,6 @@ public class NonBlocking implements CachedSupplier.PrefetchStrategy {
57
52
*/
58
53
private static final Semaphore CONCURRENT_REFRESH_LEASES = new Semaphore (MAX_CONCURRENT_REFRESHES );
59
54
60
- /**
61
- * The {@link Random} instance used for calculating jitter of the background prefetches.
62
- */
63
- private static final Random JITTER_RANDOM = new Random ();
64
-
65
55
/**
66
56
* Thread used to kick off refreshes during the prefetch window. This does not do the actual refreshing. That's left for
67
57
* the {@link #EXECUTOR}.
@@ -105,11 +95,6 @@ public class NonBlocking implements CachedSupplier.PrefetchStrategy {
105
95
*/
106
96
private final AtomicReference <ScheduledFuture <?>> refreshTask = new AtomicReference <>();
107
97
108
- /**
109
- * The minimum amount of time allowed between async refreshes, primarily adjustable for testing purposes.
110
- */
111
- private final Duration minimumRefreshFrequency ;
112
-
113
98
/**
114
99
* Whether this strategy has been shutdown (and should stop doing background refreshes)
115
100
*/
@@ -130,13 +115,7 @@ public class NonBlocking implements CachedSupplier.PrefetchStrategy {
130
115
* performing the update.
131
116
*/
132
117
public NonBlocking (String asyncThreadName ) {
133
- this (asyncThreadName , Duration .ofSeconds (60 ));
134
- }
135
-
136
- @ SdkTestInternalApi
137
- NonBlocking (String asyncThreadName , Duration minimumRefreshFrequency ) {
138
118
this .asyncThreadName = asyncThreadName + "-" + INSTANCE_NUMBER .getAndIncrement ();
139
- this .minimumRefreshFrequency = minimumRefreshFrequency ;
140
119
}
141
120
142
121
@ SdkTestInternalApi
@@ -160,54 +139,36 @@ public void prefetch(Runnable valueUpdater) {
160
139
@ Override
161
140
public <T > RefreshResult <T > fetch (Supplier <RefreshResult <T >> supplier ) {
162
141
RefreshResult <T > result = supplier .get ();
163
- if (result .staleTime () == null || result .prefetchTime () == null ) {
164
- return result ;
165
- }
166
-
167
- getRefreshTime (result ).ifPresent (this ::schedulePrefetch );
142
+ schedulePrefetch (result );
168
143
return result ;
169
144
}
170
145
171
- private Optional <Instant > getRefreshTime (RefreshResult <?> result ) {
172
- Instant minStart = Instant .now ().plus (minimumRefreshFrequency );
173
- Instant rangeStart = result .prefetchTime ().isBefore (minStart ) ? minStart : result .prefetchTime ();
174
-
175
- if (Duration .between (Instant .now (), rangeStart ).toDays () > 7 ) {
176
- log .debug (() -> "Skipping background refresh because the prefetch time is too far in the future: " + rangeStart );
177
- return Optional .empty ();
178
- }
179
-
180
- Instant maxEnd = rangeStart .plus (1 , HOURS );
181
- Instant rangeEnd = result .staleTime ().isAfter (maxEnd ) ? maxEnd : result .staleTime ().minus (1 , MINUTES );
182
-
183
- if (rangeEnd .isBefore (rangeStart )) {
184
- return Optional .of (rangeStart );
146
+ private void schedulePrefetch (RefreshResult <?> result ) {
147
+ if (shutdown || result .staleTime () == null || result .prefetchTime () == null ) {
148
+ return ;
185
149
}
186
150
187
- return Optional .of (randomTimeBetween (rangeStart , rangeEnd ));
188
- }
189
-
190
- private Instant randomTimeBetween (Instant rangeStart , Instant rangeEnd ) {
191
- Duration timeBetween = Duration .between (rangeStart , rangeEnd );
192
- return rangeStart .plusMillis (Math .abs (JITTER_RANDOM .nextLong () % timeBetween .toMillis ()));
193
- }
194
-
195
- private void schedulePrefetch (Instant refreshTime ) {
196
- if (shutdown ) {
151
+ Duration timeUntilPrefetch = Duration .between (Instant .now (), result .prefetchTime ());
152
+ if (timeUntilPrefetch .isNegative () || timeUntilPrefetch .toDays () > 7 ) {
153
+ log .debug (() -> "Skipping background refresh because the prefetch time is in the past or too far in the future: " +
154
+ result .prefetchTime ());
197
155
return ;
198
156
}
199
157
200
- Duration waitTime = Duration .between (Instant .now (), refreshTime );
201
- log .debug (() -> "Scheduling refresh attempt for " + refreshTime + " (in " + waitTime .toMillis () + " ms)" );
158
+ Instant backgroundRefreshTime = result .prefetchTime ().plusSeconds (1 );
159
+ Duration timeUntilBackgroundRefresh = timeUntilPrefetch .plusSeconds (1 );
160
+
161
+ log .debug (() -> "Scheduling refresh attempt for " + backgroundRefreshTime + " (in " +
162
+ timeUntilBackgroundRefresh .toMillis () + " ms)" );
202
163
203
164
ScheduledFuture <?> scheduledTask = SCHEDULER .schedule (() -> {
204
165
runWithInstanceThreadName (() -> {
205
- log .debug (() -> "Executing refresh attempt scheduled for " + refreshTime );
166
+ log .debug (() -> "Executing refresh attempt scheduled for " + backgroundRefreshTime );
206
167
207
168
// If the supplier has already been prefetched, this will just be a cache hit.
208
169
tryRunBackgroundTask (cachedSupplier ::get );
209
170
});
210
- }, waitTime .toMillis (), TimeUnit .MILLISECONDS );
171
+ }, timeUntilBackgroundRefresh .toMillis (), TimeUnit .MILLISECONDS );
211
172
212
173
updateTask (scheduledTask );
213
174
0 commit comments