Skip to content

Commit b570b56

Browse files
authored
Merge pull request #84 from graphql-java/time_since_dispatch
Added a instant since last dispatch value
2 parents 0eec4c8 + 90086c1 commit b570b56

File tree

4 files changed

+155
-4
lines changed

4 files changed

+155
-4
lines changed

src/main/java/org/dataloader/DataLoader.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717
package org.dataloader;
1818

1919
import org.dataloader.annotations.PublicApi;
20+
import org.dataloader.annotations.VisibleForTesting;
2021
import org.dataloader.impl.CompletableFutureKit;
2122
import org.dataloader.stats.Statistics;
2223
import org.dataloader.stats.StatisticsCollector;
2324

25+
import java.time.Clock;
26+
import java.time.Instant;
2427
import java.util.ArrayList;
2528
import java.util.Collections;
2629
import java.util.List;
@@ -52,6 +55,7 @@
5255
*
5356
* @param <K> type parameter indicating the type of the data load keys
5457
* @param <V> type parameter indicating the type of the data that is returned
58+
*
5559
* @author <a href="https://github.com/aschrijver/">Arnold Schrijver</a>
5660
* @author <a href="https://github.com/bbakerman/">Brad Baker</a>
5761
*/
@@ -69,6 +73,7 @@ public class DataLoader<K, V> {
6973
* @param batchLoadFunction the batch load function to use
7074
* @param <K> the key type
7175
* @param <V> the value type
76+
*
7277
* @return a new DataLoader
7378
*/
7479
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadFunction) {
@@ -82,6 +87,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadF
8287
* @param options the options to use
8388
* @param <K> the key type
8489
* @param <V> the value type
90+
*
8591
* @return a new DataLoader
8692
*/
8793
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadFunction, DataLoaderOptions options) {
@@ -102,6 +108,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadF
102108
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
103109
* @param <K> the key type
104110
* @param <V> the value type
111+
*
105112
* @return a new DataLoader
106113
*/
107114
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>> batchLoadFunction) {
@@ -117,7 +124,9 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>
117124
* @param options the options to use
118125
* @param <K> the key type
119126
* @param <V> the value type
127+
*
120128
* @return a new DataLoader
129+
*
121130
* @see #newDataLoaderWithTry(BatchLoader)
122131
*/
123132
@SuppressWarnings("unchecked")
@@ -132,6 +141,7 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>
132141
* @param batchLoadFunction the batch load function to use
133142
* @param <K> the key type
134143
* @param <V> the value type
144+
*
135145
* @return a new DataLoader
136146
*/
137147
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V> batchLoadFunction) {
@@ -145,6 +155,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V>
145155
* @param options the options to use
146156
* @param <K> the key type
147157
* @param <V> the value type
158+
*
148159
* @return a new DataLoader
149160
*/
150161
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V> batchLoadFunction, DataLoaderOptions options) {
@@ -165,6 +176,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V>
165176
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
166177
* @param <K> the key type
167178
* @param <V> the value type
179+
*
168180
* @return a new DataLoader
169181
*/
170182
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContext<K, Try<V>> batchLoadFunction) {
@@ -180,7 +192,9 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContex
180192
* @param options the options to use
181193
* @param <K> the key type
182194
* @param <V> the value type
195+
*
183196
* @return a new DataLoader
197+
*
184198
* @see #newDataLoaderWithTry(BatchLoader)
185199
*/
186200
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContext<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
@@ -194,6 +208,7 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContex
194208
* @param batchLoadFunction the batch load function to use
195209
* @param <K> the key type
196210
* @param <V> the value type
211+
*
197212
* @return a new DataLoader
198213
*/
199214
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V> batchLoadFunction) {
@@ -207,6 +222,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V
207222
* @param options the options to use
208223
* @param <K> the key type
209224
* @param <V> the value type
225+
*
210226
* @return a new DataLoader
211227
*/
212228
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V> batchLoadFunction, DataLoaderOptions options) {
@@ -228,6 +244,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V
228244
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
229245
* @param <K> the key type
230246
* @param <V> the value type
247+
*
231248
* @return a new DataLoader
232249
*/
233250
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoader<K, Try<V>> batchLoadFunction) {
@@ -243,7 +260,9 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
243260
* @param options the options to use
244261
* @param <K> the key type
245262
* @param <V> the value type
263+
*
246264
* @return a new DataLoader
265+
*
247266
* @see #newDataLoaderWithTry(BatchLoader)
248267
*/
249268
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoader<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
@@ -257,6 +276,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
257276
* @param batchLoadFunction the batch load function to use
258277
* @param <K> the key type
259278
* @param <V> the value type
279+
*
260280
* @return a new DataLoader
261281
*/
262282
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithContext<K, V> batchLoadFunction) {
@@ -270,6 +290,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithC
270290
* @param options the options to use
271291
* @param <K> the key type
272292
* @param <V> the value type
293+
*
273294
* @return a new DataLoader
274295
*/
275296
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithContext<K, V> batchLoadFunction, DataLoaderOptions options) {
@@ -290,6 +311,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithC
290311
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
291312
* @param <K> the key type
292313
* @param <V> the value type
314+
*
293315
* @return a new DataLoader
294316
*/
295317
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoaderWithContext<K, Try<V>> batchLoadFunction) {
@@ -305,7 +327,9 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
305327
* @param options the options to use
306328
* @param <K> the key type
307329
* @param <V> the value type
330+
*
308331
* @return a new DataLoader
332+
*
309333
* @see #newDataLoaderWithTry(BatchLoader)
310334
*/
311335
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoaderWithContext<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
@@ -337,14 +361,30 @@ private DataLoader(Object batchLoadFunction, DataLoaderOptions options) {
337361
// order of keys matter in data loader
338362
this.stats = nonNull(loaderOptions.getStatisticsCollector());
339363

340-
this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats);
364+
this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats, clock());
365+
}
366+
367+
@VisibleForTesting
368+
Clock clock() {
369+
return Clock.systemUTC();
341370
}
342371

343372
@SuppressWarnings("unchecked")
344373
private CacheMap<Object, CompletableFuture<V>> determineCacheMap(DataLoaderOptions loaderOptions) {
345374
return loaderOptions.cacheMap().isPresent() ? (CacheMap<Object, CompletableFuture<V>>) loaderOptions.cacheMap().get() : CacheMap.simpleMap();
346375
}
347376

377+
378+
/**
379+
* This returns the last instant the data loader was dispatched. When the data loader is created this value is set to now.
380+
*
381+
* @return the instant since the last dispatch
382+
*/
383+
public Instant getLastDispatchTime() {
384+
return helper.getLastDispatchTime();
385+
}
386+
387+
348388
/**
349389
* Requests to load the data with the specified key asynchronously, and returns a future of the resulting value.
350390
* <p>
@@ -353,6 +393,7 @@ private CacheMap<Object, CompletableFuture<V>> determineCacheMap(DataLoaderOptio
353393
* and returned from cache).
354394
*
355395
* @param key the key to load
396+
*
356397
* @return the future of the value
357398
*/
358399
public CompletableFuture<V> load(K key) {
@@ -370,6 +411,7 @@ public CompletableFuture<V> load(K key) {
370411
* NOTE : This will NOT cause a data load to happen. You must called {@link #load(Object)} for that to happen.
371412
*
372413
* @param key the key to check
414+
*
373415
* @return an Optional to the future of the value
374416
*/
375417
public Optional<CompletableFuture<V>> getIfPresent(K key) {
@@ -388,6 +430,7 @@ public Optional<CompletableFuture<V>> getIfPresent(K key) {
388430
* NOTE : This will NOT cause a data load to happen. You must called {@link #load(Object)} for that to happen.
389431
*
390432
* @param key the key to check
433+
*
391434
* @return an Optional to the future of the value
392435
*/
393436
public Optional<CompletableFuture<V>> getIfCompleted(K key) {
@@ -407,6 +450,7 @@ public Optional<CompletableFuture<V>> getIfCompleted(K key) {
407450
*
408451
* @param key the key to load
409452
* @param keyContext a context object that is specific to this key
453+
*
410454
* @return the future of the value
411455
*/
412456
public CompletableFuture<V> load(K key, Object keyContext) {
@@ -422,6 +466,7 @@ public CompletableFuture<V> load(K key, Object keyContext) {
422466
* and returned from cache).
423467
*
424468
* @param keys the list of keys to load
469+
*
425470
* @return the composite future of the list of values
426471
*/
427472
public CompletableFuture<List<V>> loadMany(List<K> keys) {
@@ -441,6 +486,7 @@ public CompletableFuture<List<V>> loadMany(List<K> keys) {
441486
*
442487
* @param keys the list of keys to load
443488
* @param keyContexts the list of key calling context objects
489+
*
444490
* @return the composite future of the list of values
445491
*/
446492
public CompletableFuture<List<V>> loadMany(List<K> keys, List<Object> keyContexts) {
@@ -517,6 +563,7 @@ public int dispatchDepth() {
517563
* on the next load request.
518564
*
519565
* @param key the key to remove
566+
*
520567
* @return the data loader for fluent coding
521568
*/
522569
public DataLoader<K, V> clear(K key) {
@@ -544,6 +591,7 @@ public DataLoader<K, V> clearAll() {
544591
*
545592
* @param key the key
546593
* @param value the value
594+
*
547595
* @return the data loader for fluent coding
548596
*/
549597
public DataLoader<K, V> prime(K key, V value) {
@@ -561,6 +609,7 @@ public DataLoader<K, V> prime(K key, V value) {
561609
*
562610
* @param key the key
563611
* @param error the exception to prime instead of a value
612+
*
564613
* @return the data loader for fluent coding
565614
*/
566615
public DataLoader<K, V> prime(K key, Exception error) {
@@ -578,6 +627,7 @@ public DataLoader<K, V> prime(K key, Exception error) {
578627
* If no cache key function is present in {@link DataLoaderOptions}, then the returned value equals the input key.
579628
*
580629
* @param key the input key
630+
*
581631
* @return the cache key after the input is transformed with the cache key function
582632
*/
583633
public Object getCacheKey(K key) {

src/main/java/org/dataloader/DataLoaderHelper.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import org.dataloader.impl.CompletableFutureKit;
55
import org.dataloader.stats.StatisticsCollector;
66

7+
import java.time.Clock;
8+
import java.time.Instant;
79
import java.util.ArrayList;
810
import java.util.Collection;
911
import java.util.LinkedHashSet;
@@ -13,6 +15,7 @@
1315
import java.util.Set;
1416
import java.util.concurrent.CompletableFuture;
1517
import java.util.concurrent.CompletionStage;
18+
import java.util.concurrent.atomic.AtomicReference;
1619
import java.util.stream.Collectors;
1720

1821
import static java.util.Collections.emptyList;
@@ -30,7 +33,6 @@
3033
@Internal
3134
class DataLoaderHelper<K, V> {
3235

33-
3436
static class LoaderQueueEntry<K, V> {
3537

3638
final K key;
@@ -62,14 +64,27 @@ Object getCallContext() {
6264
private final CacheMap<Object, CompletableFuture<V>> futureCache;
6365
private final List<LoaderQueueEntry<K, CompletableFuture<V>>> loaderQueue;
6466
private final StatisticsCollector stats;
67+
private final Clock clock;
68+
private final AtomicReference<Instant> lastDispatchTime;
6569

66-
DataLoaderHelper(DataLoader<K, V> dataLoader, Object batchLoadFunction, DataLoaderOptions loaderOptions, CacheMap<Object, CompletableFuture<V>> futureCache, StatisticsCollector stats) {
70+
DataLoaderHelper(DataLoader<K, V> dataLoader, Object batchLoadFunction, DataLoaderOptions loaderOptions, CacheMap<Object, CompletableFuture<V>> futureCache, StatisticsCollector stats, Clock clock) {
6771
this.dataLoader = dataLoader;
6872
this.batchLoadFunction = batchLoadFunction;
6973
this.loaderOptions = loaderOptions;
7074
this.futureCache = futureCache;
7175
this.loaderQueue = new ArrayList<>();
7276
this.stats = stats;
77+
this.clock = clock;
78+
this.lastDispatchTime = new AtomicReference<>();
79+
this.lastDispatchTime.set(now());
80+
}
81+
82+
private Instant now() {
83+
return Instant.now(clock);
84+
}
85+
86+
public Instant getLastDispatchTime() {
87+
return lastDispatchTime.get();
7388
}
7489

7590
Optional<CompletableFuture<V>> getIfPresent(K key) {
@@ -146,7 +161,7 @@ Object getCacheKey(K key) {
146161
@SuppressWarnings("unchecked")
147162
Object getCacheKeyWithContext(K key, Object context) {
148163
return loaderOptions.cacheKeyFunction().isPresent() ?
149-
loaderOptions.cacheKeyFunction().get().getKeyWithContext(key, context): key;
164+
loaderOptions.cacheKeyFunction().get().getKeyWithContext(key, context) : key;
150165
}
151166

152167
DispatchResult<V> dispatch() {
@@ -163,6 +178,7 @@ DispatchResult<V> dispatch() {
163178
callContexts.add(entry.getCallContext());
164179
});
165180
loaderQueue.clear();
181+
lastDispatchTime.set(now());
166182
}
167183
if (!batchingEnabled || keys.isEmpty()) {
168184
return new DispatchResult<>(CompletableFuture.completedFuture(emptyList()), 0);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.dataloader.annotations;
2+
3+
import java.lang.annotation.Retention;
4+
import java.lang.annotation.RetentionPolicy;
5+
import java.lang.annotation.Target;
6+
7+
import static java.lang.annotation.ElementType.CONSTRUCTOR;
8+
import static java.lang.annotation.ElementType.FIELD;
9+
import static java.lang.annotation.ElementType.METHOD;
10+
11+
/**
12+
* Marks fields, methods etc as more visible than actually needed for testing purposes.
13+
*/
14+
@Retention(RetentionPolicy.RUNTIME)
15+
@Target(value = {CONSTRUCTOR, METHOD, FIELD})
16+
@Internal
17+
public @interface VisibleForTesting {
18+
}

0 commit comments

Comments
 (0)