Skip to content

Commit d691f88

Browse files
committed
found a buf where the cache set is done on entries that are already in cache - fix it
1 parent d8078e0 commit d691f88

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed

build.gradle

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ version = releaseVersion ? releaseVersion : getDevelopmentVersion()
4040
group = 'com.graphql-java'
4141
description = 'A pure Java 8 port of Facebook Dataloader'
4242

43+
gradle.buildFinished { buildResult ->
44+
println "*******************************"
45+
println "*"
46+
if (buildResult.failure != null) {
47+
println "* FAILURE - ${buildResult.failure}"
48+
} else {
49+
println "* SUCCESS"
50+
}
51+
println "* Version: $version"
52+
println "*"
53+
println "*******************************"
54+
}
55+
4356
repositories {
4457
mavenCentral()
4558
mavenLocal()

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

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -362,22 +362,21 @@ CompletionStage<List<V>> invokeLoader(List<K> keys, List<Object> keyContexts, bo
362362
// and then fill in their values
363363
//
364364
CompletionStage<List<V>> batchLoad = invokeLoader(cacheMissedKeys, cacheMissedContexts);
365-
CompletionStage<List<V>> assembledValues = batchLoad.thenApply(batchedValues -> {
365+
CompletionStage<CacheMissedData<K, V>> assembledValues = batchLoad.thenApply(batchedValues -> {
366366
assertResultSize(cacheMissedKeys, batchedValues);
367367

368368
for (int i = 0; i < batchedValues.size(); i++) {
369369
K missedKey = cacheMissedKeys.get(i);
370370
V v = batchedValues.get(i);
371371
valuesInKeyOrder.put(missedKey, v);
372372
}
373-
return new ArrayList<>(valuesInKeyOrder.values());
373+
374+
return new CacheMissedData<>(cacheMissedKeys, batchedValues, new ArrayList<>(valuesInKeyOrder.values()));
374375
});
375376
//
376377
// fire off a call to the ValueCache to allow it to set values into the
377378
// cache now that we have them
378-
assembledValues = setToValueCache(keys, assembledValues);
379-
380-
return assembledValues;
379+
return setToValueCache(assembledValues);
381380
}
382381
});
383382
}
@@ -454,27 +453,39 @@ private CompletableFuture<List<Try<V>>> getFromValueCache(List<K> keys) {
454453
}
455454
}
456455

457-
private CompletionStage<List<V>> setToValueCache(List<K> keys, CompletionStage<List<V>> assembledValues) {
456+
static class CacheMissedData<K, V> {
457+
final List<K> missedKeys;
458+
final List<V> missedValues;
459+
final List<V> assembledValues;
460+
461+
CacheMissedData(List<K> missedKeys, List<V> missedValues, List<V> assembledValues) {
462+
this.missedKeys = missedKeys;
463+
this.missedValues = missedValues;
464+
this.assembledValues = assembledValues;
465+
}
466+
}
467+
468+
private CompletionStage<List<V>> setToValueCache(CompletionStage<CacheMissedData<K, V>> assembledValues) {
458469
try {
459470
boolean completeValueAfterCacheSet = loaderOptions.getValueCacheOptions().isCompleteValueAfterCacheSet();
460471
if (completeValueAfterCacheSet) {
461-
return assembledValues.thenCompose(values -> nonNull(valueCache
462-
.setValues(keys, values), () -> "Your ValueCache.setValues function MUST return a non null promise")
472+
return assembledValues.thenCompose(cacheMissedData -> nonNull(valueCache
473+
.setValues(cacheMissedData.missedKeys, cacheMissedData.missedValues), () -> "Your ValueCache.setValues function MUST return a non null promise")
463474
// we dont trust the set cache to give us the values back - we have them - lets use them
464475
// if the cache set fails - then they wont be in cache and maybe next time they will
465-
.handle((ignored, setExIgnored) -> values));
476+
.handle((ignored, setExIgnored) -> cacheMissedData.assembledValues));
466477
} else {
467-
return assembledValues.thenApply(values -> {
478+
return assembledValues.thenApply(cacheMissedData -> {
468479
// no one is waiting for the set to happen here so if its truly async
469480
// it will happen eventually but no result will be dependant on it
470-
valueCache.setValues(keys, values);
471-
return values;
481+
valueCache.setValues(cacheMissedData.missedKeys, cacheMissedData.missedValues);
482+
return cacheMissedData.assembledValues;
472483
});
473484
}
474485
} catch (RuntimeException ignored) {
475486
// if we cant set values back into the cache - so be it - this must be a faulty
476487
// ValueCache implementation
477-
return assembledValues;
488+
return assembledValues.thenApply(cacheMissedData -> cacheMissedData.assembledValues);
478489
}
479490
}
480491

src/test/java/org/dataloader/DataLoaderValueCacheTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,9 @@ public CompletableFuture<List<Try<Object>>> getValues(List<String> keys) {
288288
assertThat(loadCalls, equalTo(singletonList(asList("missC", "missD"))));
289289

290290
List<Object> values = new ArrayList<>(customValueCache.asMap().values());
291-
assertThat(values, equalTo(asList("a", "b", "missC", "missD")));
291+
// it will only set back in values that are missed - it wont set in values that successfully
292+
// came out of the cache
293+
assertThat(values, equalTo(asList("missC", "missD")));
292294
}
293295

294296
@Test

0 commit comments

Comments
 (0)