return null;
}
- CompletableFuture<OperationOutcome> future = retrievers.get(name);
- if (future != null) {
- return future;
- }
+ /*
+ * Return any existing future, if it wasn't canceled. Otherwise, start a new
+ * request.
+ */
- future = params.start();
+ // @formatter:off
+ CompletableFuture<OperationOutcome> oldFuture =
+ retrievers.compute(name, (key, future) -> (future == null || future.isCancelled() ? null : future));
+ // @formatter:on
- CompletableFuture<OperationOutcome> oldFuture = retrievers.putIfAbsent(name, future);
if (oldFuture != null) {
+ return oldFuture;
+ }
+
+ /*
+ * Note: must NOT invoke params.start() within retrievers.compute(), as start()
+ * may invoke obtain() which would cause a recursive update to the retrievers map.
+ */
+ CompletableFuture<OperationOutcome> future = params.start();
+
+ if ((oldFuture = retrievers.putIfAbsent(name, future)) != null) {
future.cancel(false);
return oldFuture;
}