Skip to content

Added a instant since last dispatch value #84

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion src/main/java/org/dataloader/DataLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
package org.dataloader;

import org.dataloader.annotations.PublicApi;
import org.dataloader.annotations.VisibleForTesting;
import org.dataloader.impl.CompletableFutureKit;
import org.dataloader.stats.Statistics;
import org.dataloader.stats.StatisticsCollector;

import java.time.Clock;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -52,6 +55,7 @@
*
* @param <K> type parameter indicating the type of the data load keys
* @param <V> type parameter indicating the type of the data that is returned
*
* @author <a href="https://github.com/aschrijver/">Arnold Schrijver</a>
* @author <a href="https://github.com/bbakerman/">Brad Baker</a>
*/
Expand All @@ -69,6 +73,7 @@ public class DataLoader<K, V> {
* @param batchLoadFunction the batch load function to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadFunction) {
Expand All @@ -82,6 +87,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadF
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -102,6 +108,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoader<K, V> batchLoadF
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>> batchLoadFunction) {
Expand All @@ -117,7 +124,9 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*
* @see #newDataLoaderWithTry(BatchLoader)
*/
@SuppressWarnings("unchecked")
Expand All @@ -132,6 +141,7 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoader<K, Try<V>
* @param batchLoadFunction the batch load function to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V> batchLoadFunction) {
Expand All @@ -145,6 +155,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V>
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -165,6 +176,7 @@ public static <K, V> DataLoader<K, V> newDataLoader(BatchLoaderWithContext<K, V>
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContext<K, Try<V>> batchLoadFunction) {
Expand All @@ -180,7 +192,9 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContex
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*
* @see #newDataLoaderWithTry(BatchLoader)
*/
public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContext<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -194,6 +208,7 @@ public static <K, V> DataLoader<K, V> newDataLoaderWithTry(BatchLoaderWithContex
* @param batchLoadFunction the batch load function to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V> batchLoadFunction) {
Expand All @@ -207,6 +222,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -228,6 +244,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoader<K, V
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoader<K, Try<V>> batchLoadFunction) {
Expand All @@ -243,7 +260,9 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*
* @see #newDataLoaderWithTry(BatchLoader)
*/
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoader<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -257,6 +276,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
* @param batchLoadFunction the batch load function to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithContext<K, V> batchLoadFunction) {
Expand All @@ -270,6 +290,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithC
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithContext<K, V> batchLoadFunction, DataLoaderOptions options) {
Expand All @@ -290,6 +311,7 @@ public static <K, V> DataLoader<K, V> newMappedDataLoader(MappedBatchLoaderWithC
* @param batchLoadFunction the batch load function to use that uses {@link org.dataloader.Try} objects
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*/
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoaderWithContext<K, Try<V>> batchLoadFunction) {
Expand All @@ -305,7 +327,9 @@ public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoad
* @param options the options to use
* @param <K> the key type
* @param <V> the value type
*
* @return a new DataLoader
*
* @see #newDataLoaderWithTry(BatchLoader)
*/
public static <K, V> DataLoader<K, V> newMappedDataLoaderWithTry(MappedBatchLoaderWithContext<K, Try<V>> batchLoadFunction, DataLoaderOptions options) {
Expand Down Expand Up @@ -337,14 +361,30 @@ private DataLoader(Object batchLoadFunction, DataLoaderOptions options) {
// order of keys matter in data loader
this.stats = nonNull(loaderOptions.getStatisticsCollector());

this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats);
this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats, clock());
}

@VisibleForTesting
Clock clock() {
return Clock.systemUTC();
}

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


/**
* This returns the last instant the data loader was dispatched. When the data loader is created this value is set to now.
*
* @return the instant since the last dispatch
*/
public Instant getLastDispatchTime() {
return helper.getLastDispatchTime();
}


/**
* Requests to load the data with the specified key asynchronously, and returns a future of the resulting value.
* <p>
Expand All @@ -353,6 +393,7 @@ private CacheMap<Object, CompletableFuture<V>> determineCacheMap(DataLoaderOptio
* and returned from cache).
*
* @param key the key to load
*
* @return the future of the value
*/
public CompletableFuture<V> load(K key) {
Expand All @@ -370,6 +411,7 @@ public CompletableFuture<V> load(K key) {
* NOTE : This will NOT cause a data load to happen. You must called {@link #load(Object)} for that to happen.
*
* @param key the key to check
*
* @return an Optional to the future of the value
*/
public Optional<CompletableFuture<V>> getIfPresent(K key) {
Expand All @@ -388,6 +430,7 @@ public Optional<CompletableFuture<V>> getIfPresent(K key) {
* NOTE : This will NOT cause a data load to happen. You must called {@link #load(Object)} for that to happen.
*
* @param key the key to check
*
* @return an Optional to the future of the value
*/
public Optional<CompletableFuture<V>> getIfCompleted(K key) {
Expand All @@ -407,6 +450,7 @@ public Optional<CompletableFuture<V>> getIfCompleted(K key) {
*
* @param key the key to load
* @param keyContext a context object that is specific to this key
*
* @return the future of the value
*/
public CompletableFuture<V> load(K key, Object keyContext) {
Expand All @@ -422,6 +466,7 @@ public CompletableFuture<V> load(K key, Object keyContext) {
* and returned from cache).
*
* @param keys the list of keys to load
*
* @return the composite future of the list of values
*/
public CompletableFuture<List<V>> loadMany(List<K> keys) {
Expand All @@ -441,6 +486,7 @@ public CompletableFuture<List<V>> loadMany(List<K> keys) {
*
* @param keys the list of keys to load
* @param keyContexts the list of key calling context objects
*
* @return the composite future of the list of values
*/
public CompletableFuture<List<V>> loadMany(List<K> keys, List<Object> keyContexts) {
Expand Down Expand Up @@ -517,6 +563,7 @@ public int dispatchDepth() {
* on the next load request.
*
* @param key the key to remove
*
* @return the data loader for fluent coding
*/
public DataLoader<K, V> clear(K key) {
Expand Down Expand Up @@ -544,6 +591,7 @@ public DataLoader<K, V> clearAll() {
*
* @param key the key
* @param value the value
*
* @return the data loader for fluent coding
*/
public DataLoader<K, V> prime(K key, V value) {
Expand All @@ -561,6 +609,7 @@ public DataLoader<K, V> prime(K key, V value) {
*
* @param key the key
* @param error the exception to prime instead of a value
*
* @return the data loader for fluent coding
*/
public DataLoader<K, V> prime(K key, Exception error) {
Expand All @@ -578,6 +627,7 @@ public DataLoader<K, V> prime(K key, Exception error) {
* If no cache key function is present in {@link DataLoaderOptions}, then the returned value equals the input key.
*
* @param key the input key
*
* @return the cache key after the input is transformed with the cache key function
*/
public Object getCacheKey(K key) {
Expand Down
22 changes: 19 additions & 3 deletions src/main/java/org/dataloader/DataLoaderHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.dataloader.impl.CompletableFutureKit;
import org.dataloader.stats.StatisticsCollector;

import java.time.Clock;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
Expand All @@ -13,6 +15,7 @@
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

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


static class LoaderQueueEntry<K, V> {

final K key;
Expand Down Expand Up @@ -62,14 +64,27 @@ Object getCallContext() {
private final CacheMap<Object, CompletableFuture<V>> futureCache;
private final List<LoaderQueueEntry<K, CompletableFuture<V>>> loaderQueue;
private final StatisticsCollector stats;
private final Clock clock;
private final AtomicReference<Instant> lastDispatchTime;

DataLoaderHelper(DataLoader<K, V> dataLoader, Object batchLoadFunction, DataLoaderOptions loaderOptions, CacheMap<Object, CompletableFuture<V>> futureCache, StatisticsCollector stats) {
DataLoaderHelper(DataLoader<K, V> dataLoader, Object batchLoadFunction, DataLoaderOptions loaderOptions, CacheMap<Object, CompletableFuture<V>> futureCache, StatisticsCollector stats, Clock clock) {
this.dataLoader = dataLoader;
this.batchLoadFunction = batchLoadFunction;
this.loaderOptions = loaderOptions;
this.futureCache = futureCache;
this.loaderQueue = new ArrayList<>();
this.stats = stats;
this.clock = clock;
this.lastDispatchTime = new AtomicReference<>();
this.lastDispatchTime.set(now());
}

private Instant now() {
return Instant.now(clock);
}

public Instant getLastDispatchTime() {
return lastDispatchTime.get();
}

Optional<CompletableFuture<V>> getIfPresent(K key) {
Expand Down Expand Up @@ -146,7 +161,7 @@ Object getCacheKey(K key) {
@SuppressWarnings("unchecked")
Object getCacheKeyWithContext(K key, Object context) {
return loaderOptions.cacheKeyFunction().isPresent() ?
loaderOptions.cacheKeyFunction().get().getKeyWithContext(key, context): key;
loaderOptions.cacheKeyFunction().get().getKeyWithContext(key, context) : key;
}

DispatchResult<V> dispatch() {
Expand All @@ -163,6 +178,7 @@ DispatchResult<V> dispatch() {
callContexts.add(entry.getCallContext());
});
loaderQueue.clear();
lastDispatchTime.set(now());
}
if (!batchingEnabled || keys.isEmpty()) {
return new DispatchResult<>(CompletableFuture.completedFuture(emptyList()), 0);
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/dataloader/annotations/VisibleForTesting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.dataloader.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;

/**
* Marks fields, methods etc as more visible than actually needed for testing purposes.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {CONSTRUCTOR, METHOD, FIELD})
@Internal
public @interface VisibleForTesting {
}
Loading