Skip to content

Commit 11a7348

Browse files
authored
Merge pull request #86 from graphql-java/clock-updates
Clock improvements and test re-org
2 parents 77a8ed3 + 9ff5e5f commit 11a7348

10 files changed

+164
-78
lines changed

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.dataloader.stats.StatisticsCollector;
2424

2525
import java.time.Clock;
26+
import java.time.Duration;
2627
import java.time.Instant;
2728
import java.util.ArrayList;
2829
import java.util.Collections;
@@ -404,19 +405,21 @@ public DataLoader(BatchLoader<K, V> batchLoadFunction, DataLoaderOptions options
404405
this((Object) batchLoadFunction, options);
405406
}
406407

408+
@VisibleForTesting
407409
DataLoader(Object batchLoadFunction, DataLoaderOptions options) {
410+
this(batchLoadFunction, options, Clock.systemUTC());
411+
}
412+
413+
@VisibleForTesting
414+
DataLoader(Object batchLoadFunction, DataLoaderOptions options, Clock clock) {
408415
DataLoaderOptions loaderOptions = options == null ? new DataLoaderOptions() : options;
409416
this.futureCache = determineCacheMap(loaderOptions);
410417
// order of keys matter in data loader
411418
this.stats = nonNull(loaderOptions.getStatisticsCollector());
412419

413-
this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats, clock());
420+
this.helper = new DataLoaderHelper<>(this, batchLoadFunction, loaderOptions, this.futureCache, this.stats, clock);
414421
}
415422

416-
@VisibleForTesting
417-
Clock clock() {
418-
return Clock.systemUTC();
419-
}
420423

421424
@SuppressWarnings("unchecked")
422425
private CacheMap<Object, CompletableFuture<V>> determineCacheMap(DataLoaderOptions loaderOptions) {
@@ -433,6 +436,15 @@ public Instant getLastDispatchTime() {
433436
return helper.getLastDispatchTime();
434437
}
435438

439+
/**
440+
* This returns the {@link Duration} since the data loader was dispatched. When the data loader is created this is zero.
441+
*
442+
* @return the time duration since the last dispatch
443+
*/
444+
public Duration getTimeSinceDispatch() {
445+
return Duration.between(helper.getLastDispatchTime(), helper.now());
446+
}
447+
436448

437449
/**
438450
* Requests to load the data with the specified key asynchronously, and returns a future of the resulting value.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ Object getCallContext() {
7979
this.lastDispatchTime.set(now());
8080
}
8181

82-
private Instant now() {
83-
return Instant.now(clock);
82+
Instant now() {
83+
return clock.instant();
8484
}
8585

8686
public Instant getLastDispatchTime() {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.dataloader;
2+
3+
import java.time.Clock;
4+
5+
public class ClockDataLoader<K, V> extends DataLoader<K, V> {
6+
7+
ClockDataLoader(Object batchLoadFunction, Clock clock) {
8+
this(batchLoadFunction, null, clock);
9+
}
10+
11+
ClockDataLoader(Object batchLoadFunction, DataLoaderOptions options, Clock clock) {
12+
super(batchLoadFunction, options, clock);
13+
}
14+
15+
}

src/test/java/org/dataloader/DataLoaderMapBatchLoaderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
import static org.awaitility.Awaitility.await;
1717
import static org.dataloader.DataLoaderFactory.newDataLoader;
1818
import static org.dataloader.DataLoaderOptions.newOptions;
19-
import static org.dataloader.TestKit.futureError;
20-
import static org.dataloader.TestKit.listFrom;
19+
import static org.dataloader.fixtures.TestKit.futureError;
20+
import static org.dataloader.fixtures.TestKit.listFrom;
2121
import static org.dataloader.impl.CompletableFutureKit.cause;
2222
import static org.hamcrest.Matchers.equalTo;
2323
import static org.hamcrest.Matchers.instanceOf;

src/test/java/org/dataloader/DataLoaderTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.dataloader;
1818

19+
import org.dataloader.fixtures.JsonObject;
20+
import org.dataloader.fixtures.TestKit;
1921
import org.dataloader.fixtures.User;
2022
import org.dataloader.fixtures.UserManager;
2123
import org.dataloader.impl.CompletableFutureKit;
@@ -37,7 +39,7 @@
3739
import static org.awaitility.Awaitility.await;
3840
import static org.dataloader.DataLoaderFactory.newDataLoader;
3941
import static org.dataloader.DataLoaderOptions.newOptions;
40-
import static org.dataloader.TestKit.listFrom;
42+
import static org.dataloader.fixtures.TestKit.listFrom;
4143
import static org.dataloader.impl.CompletableFutureKit.cause;
4244
import static org.hamcrest.Matchers.empty;
4345
import static org.hamcrest.Matchers.equalTo;
Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,45 @@
11
package org.dataloader;
22

3+
import org.dataloader.fixtures.TestingClock;
34
import org.junit.Test;
45

5-
import java.time.Clock;
6-
import java.time.Duration;
76
import java.time.Instant;
8-
import java.time.ZoneId;
9-
import java.util.concurrent.CompletableFuture;
10-
import java.util.concurrent.atomic.AtomicReference;
117

8+
import static org.dataloader.fixtures.TestKit.keysAsValues;
129
import static org.hamcrest.Matchers.equalTo;
1310
import static org.junit.Assert.assertThat;
1411

1512
@SuppressWarnings("UnusedReturnValue")
1613
public class DataLoaderTimeTest {
1714

18-
private <T> BatchLoader<T, T> keysAsValues() {
19-
return CompletableFuture::completedFuture;
20-
}
21-
22-
AtomicReference<Clock> clockRef = new AtomicReference<>();
2315

2416
@Test
2517
public void should_set_and_instant_if_dispatched() {
26-
Clock clock = zeroEpoch();
27-
clockRef.set(clock);
28-
29-
Instant startInstant = now();
3018

31-
@SuppressWarnings("deprecation")
32-
DataLoader<Integer, Integer> dataLoader = new DataLoader<Integer, Integer>(keysAsValues()) {
33-
@Override
34-
Clock clock() {
35-
return clockRef.get();
36-
}
37-
};
19+
TestingClock clock = new TestingClock();
20+
DataLoader<Integer, Integer> dataLoader = new ClockDataLoader<>(keysAsValues(), clock);
21+
Instant then = clock.instant();
3822

39-
long sinceMS = msSince(dataLoader.getLastDispatchTime());
23+
long sinceMS = dataLoader.getTimeSinceDispatch().toMillis();
4024
assertThat(sinceMS, equalTo(0L));
41-
assertThat(startInstant, equalTo(dataLoader.getLastDispatchTime()));
25+
assertThat(then, equalTo(dataLoader.getLastDispatchTime()));
4226

43-
jump(clock, 1000);
44-
dataLoader.dispatch();
27+
then = clock.instant();
28+
clock.jump(1000);
4529

46-
sinceMS = msSince(dataLoader.getLastDispatchTime());
30+
sinceMS = dataLoader.getTimeSinceDispatch().toMillis();
4731
assertThat(sinceMS, equalTo(1000L));
48-
}
32+
assertThat(then, equalTo(dataLoader.getLastDispatchTime()));
4933

50-
private long msSince(Instant lastDispatchTime) {
51-
return Duration.between(lastDispatchTime, now()).toMillis();
52-
}
34+
// dispatch and hence reset the time of last dispatch
35+
then = clock.instant();
36+
dataLoader.dispatch();
5337

54-
private Instant now() {
55-
return Instant.now(clockRef.get());
56-
}
38+
sinceMS = dataLoader.getTimeSinceDispatch().toMillis();
39+
assertThat(sinceMS, equalTo(0L));
40+
assertThat(then, equalTo(dataLoader.getLastDispatchTime()));
5741

58-
private Clock jump(Clock clock, int millis) {
59-
clock = Clock.offset(clock, Duration.ofMillis(millis));
60-
clockRef.set(clock);
61-
return clock;
6242
}
6343

64-
private Clock zeroEpoch() {
65-
return Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault());
66-
}
6744

6845
}

src/test/java/org/dataloader/TestKit.java

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/test/java/org/dataloader/JsonObject.java renamed to src/test/java/org/dataloader/fixtures/JsonObject.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
package org.dataloader;
1+
package org.dataloader.fixtures;
22

33
import java.util.LinkedHashMap;
44
import java.util.Map;
55
import java.util.stream.Stream;
66

7-
class JsonObject {
7+
public class JsonObject {
88

99
private final Map<String, Object> values;
1010

11-
JsonObject() {
11+
public JsonObject() {
1212
values = new LinkedHashMap<>();
1313
}
1414

@@ -19,8 +19,12 @@ public JsonObject put(String key, Object value) {
1919

2020
@Override
2121
public boolean equals(Object o) {
22-
if (this == o) return true;
23-
if (o == null || getClass() != o.getClass()) return false;
22+
if (this == o) {
23+
return true;
24+
}
25+
if (o == null || getClass() != o.getClass()) {
26+
return false;
27+
}
2428

2529
JsonObject that = (JsonObject) o;
2630

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.dataloader.fixtures;
2+
3+
import org.dataloader.BatchLoader;
4+
import org.dataloader.DataLoader;
5+
import org.dataloader.DataLoaderFactory;
6+
import org.dataloader.DataLoaderOptions;
7+
8+
import java.util.ArrayList;
9+
import java.util.Collection;
10+
import java.util.List;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.stream.Collectors;
13+
14+
import static org.dataloader.impl.CompletableFutureKit.failedFuture;
15+
16+
public class TestKit {
17+
18+
public static <T> BatchLoader<T, T> keysAsValues() {
19+
return CompletableFuture::completedFuture;
20+
}
21+
22+
public static <K, V> BatchLoader<K, V> keysAsValues(List<List<K>> loadCalls) {
23+
return keys -> {
24+
List<K> ks = new ArrayList<>(keys);
25+
loadCalls.add(ks);
26+
@SuppressWarnings("unchecked")
27+
List<V> values = keys.stream()
28+
.map(k -> (V) k)
29+
.collect(Collectors.toList());
30+
return CompletableFuture.completedFuture(values);
31+
};
32+
}
33+
34+
public static <K, V> DataLoader<K, V> idLoader(List<List<K>> loadCalls) {
35+
return idLoader(null, loadCalls);
36+
}
37+
38+
public static <K, V> DataLoader<K, V> idLoader(DataLoaderOptions options, List<List<K>> loadCalls) {
39+
return DataLoaderFactory.newDataLoader(keysAsValues(loadCalls), options);
40+
}
41+
42+
public static Collection<Integer> listFrom(int i, int max) {
43+
List<Integer> ints = new ArrayList<>();
44+
for (int j = i; j < max; j++) {
45+
ints.add(j);
46+
}
47+
return ints;
48+
}
49+
50+
public static <V> CompletableFuture<V> futureError() {
51+
return failedFuture(new IllegalStateException("Error"));
52+
}
53+
54+
public static void snooze(int millis) {
55+
try {
56+
Thread.sleep(millis);
57+
} catch (InterruptedException e) {
58+
throw new RuntimeException(e);
59+
}
60+
}
61+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.dataloader.fixtures;
2+
3+
import java.time.Clock;
4+
import java.time.Duration;
5+
import java.time.Instant;
6+
import java.time.ZoneId;
7+
8+
/**
9+
* A mutable (but time fixed) clock that can jump forward or back in time
10+
*/
11+
public class TestingClock extends Clock {
12+
13+
private Clock clock;
14+
15+
public TestingClock() {
16+
clock = Clock.fixed(Instant.ofEpochMilli(0), ZoneId.systemDefault());
17+
}
18+
19+
public Clock jump(int millisDelta) {
20+
clock = Clock.offset(clock, Duration.ofMillis(millisDelta));
21+
return clock;
22+
}
23+
24+
@Override
25+
public ZoneId getZone() {
26+
return clock.getZone();
27+
}
28+
29+
@Override
30+
public Clock withZone(ZoneId zone) {
31+
return clock.withZone(zone);
32+
}
33+
34+
@Override
35+
public Instant instant() {
36+
return clock.instant();
37+
}
38+
}

0 commit comments

Comments
 (0)