@@ -316,6 +316,94 @@ public void should_Resolve_to_error_to_indicate_failure() {
316316 assertThat (loadCalls , equalTo (Arrays .asList (Collections .singletonList (1 ), Collections .singletonList (2 ))));
317317 }
318318
319+ @ Test
320+ public void should_Represent_failures_and_successes_simultaneously () {
321+ ArrayList <Collection > loadCalls = new ArrayList <>();
322+ DataLoader <Integer , Integer > evenLoader = idLoaderWithErrors (new DataLoaderOptions (), loadCalls );
323+
324+ Future <Integer > future1 = evenLoader .load (1 );
325+ Future <Integer > future2 = evenLoader .load (2 );
326+ evenLoader .dispatch ();
327+
328+ await ().until (future1 ::isComplete );
329+ assertThat (future1 .failed (), is (true ));
330+ assertThat (future1 .cause (), instanceOf (IllegalStateException .class ));
331+
332+ await ().until (future2 ::isComplete );
333+ assertThat (future2 .result (), equalTo (2 ));
334+ assertThat (loadCalls , equalTo (Collections .singletonList (Arrays .asList (1 , 2 ))));
335+ }
336+
337+ @ Test
338+ public void should_Cache_failed_fetches () {
339+ ArrayList <Collection > loadCalls = new ArrayList <>();
340+ DataLoader <Integer , Integer > errorLoader = idLoaderAllErrors (new DataLoaderOptions (), loadCalls );
341+
342+ Future <Integer > future1 = errorLoader .load (1 );
343+ errorLoader .dispatch ();
344+
345+ await ().until (future1 ::isComplete );
346+ assertThat (future1 .failed (), is (true ));
347+ assertThat (future1 .cause (), instanceOf (IllegalStateException .class ));
348+
349+ Future <Integer > future2 = errorLoader .load (1 );
350+ errorLoader .dispatch ();
351+
352+ await ().until (future2 ::isComplete );
353+ assertThat (future2 .failed (), is (true ));
354+ assertThat (future2 .cause (), instanceOf (IllegalStateException .class ));
355+ assertThat (loadCalls , equalTo (Collections .singletonList (Collections .singletonList (1 ))));
356+ }
357+
358+ @ Test
359+ public void should_Handle_priming_the_cache_with_an_error () {
360+ ArrayList <Collection > loadCalls = new ArrayList <>();
361+ DataLoader <Integer , Integer > identityLoader = idLoader (new DataLoaderOptions (), loadCalls );
362+
363+ identityLoader .prime (1 , new IllegalStateException ("Error" ));
364+
365+ Future <Integer > future1 = identityLoader .load (1 );
366+ identityLoader .dispatch ();
367+
368+ await ().until (future1 ::isComplete );
369+ assertThat (future1 .failed (), is (true ));
370+ assertThat (future1 .cause (), instanceOf (IllegalStateException .class ));
371+ assertThat (loadCalls , equalTo (Collections .emptyList ()));
372+ }
373+
374+ @ Test
375+ public void should_Clear_values_from_cache_after_errors () {
376+ ArrayList <Collection > loadCalls = new ArrayList <>();
377+ DataLoader <Integer , Integer > errorLoader = idLoaderAllErrors (new DataLoaderOptions (), loadCalls );
378+
379+ Future <Integer > future1 = errorLoader .load (1 );
380+ future1 .setHandler (rh -> {
381+ if (rh .failed ()) {
382+ // Presumably determine if this error is transient, and only clear the cache in that case.
383+ errorLoader .clear (1 );
384+ }
385+ });
386+ errorLoader .dispatch ();
387+
388+ await ().until (future1 ::isComplete );
389+ assertThat (future1 .failed (), is (true ));
390+ assertThat (future1 .cause (), instanceOf (IllegalStateException .class ));
391+
392+ Future <Integer > future2 = errorLoader .load (1 );
393+ future2 .setHandler (rh -> {
394+ if (rh .failed ()) {
395+ // Again, only do this if you can determine the error is transient.
396+ errorLoader .clear (1 );
397+ }
398+ });
399+ errorLoader .dispatch ();
400+
401+ await ().until (future2 ::isComplete );
402+ assertThat (future2 .failed (), is (true ));
403+ assertThat (future2 .cause (), instanceOf (IllegalStateException .class ));
404+ assertThat (loadCalls , equalTo (Arrays .asList (Collections .singletonList (1 ), Collections .singletonList (1 ))));
405+ }
406+
319407 @ SuppressWarnings ("unchecked" )
320408 private static <K , V > DataLoader <K , V > idLoader (DataLoaderOptions options , List <Collection > loadCalls ) {
321409 return new DataLoader <>(keys -> {
@@ -325,6 +413,17 @@ private static <K, V> DataLoader<K, V> idLoader(DataLoaderOptions options, List<
325413 }, options );
326414 }
327415
416+ @ SuppressWarnings ("unchecked" )
417+ private static <K , V > DataLoader <K , V > idLoaderAllErrors (DataLoaderOptions options , List <Collection > loadCalls ) {
418+ return new DataLoader <>(keys -> {
419+ loadCalls .add (new ArrayList (keys ));
420+ List <Future > futures = keys .stream ()
421+ .map (key -> Future .failedFuture (new IllegalStateException ("Error" )))
422+ .collect (Collectors .toList ());
423+ return CompositeFuture .all (futures );
424+ }, options );
425+ }
426+
328427 @ SuppressWarnings ("unchecked" )
329428 private static DataLoader <Integer , Integer > idLoaderWithErrors (
330429 DataLoaderOptions options , List <Collection > loadCalls ) {
0 commit comments