From 681110544c1eca0a06a0a8f964a4a75a46277ae0 Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Sun, 2 Jun 2024 19:54:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20report=20exception=20info=20of=20hop=20?= =?UTF-8?q?handle,=20errors=20should=20never=20pass=20silently=20?= =?UTF-8?q?=F0=9F=92=A3=20=F0=9F=91=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cffu/CompletableFutureUtils.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index ae22c2e6..15c23879 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -1271,7 +1271,7 @@ C peek(C cf, BiConsumer action) { requireNonNull(cf, "cf is null"); requireNonNull(action, "action is null"); - cf.whenComplete(action).exceptionally(CompletableFutureUtils::reportExceptionInfoOfPeekAction); + cf.whenComplete(action).exceptionally(ex -> reportException("Exception occurred in the action of peek:", ex)); return cf; } @@ -1321,16 +1321,17 @@ C peekAsync(C cf, BiConsumer action, Executor exec requireNonNull(action, "action is null"); requireNonNull(executor, "executor is null"); - cf.whenCompleteAsync(action, executor).exceptionally(CompletableFutureUtils::reportExceptionInfoOfPeekAction); + cf.whenCompleteAsync(action, executor).exceptionally(ex -> + reportException("Exception occurred in the action of peekAsync:", ex)); return cf; } @Nullable - private static T reportExceptionInfoOfPeekAction(Throwable ex) { + private static T reportException(String msg, Throwable ex) { StringWriter sw = new StringWriter(4096); PrintWriter writer = new PrintWriter(sw); - writer.println("Exception occurred in the action of peek:"); + writer.println(msg); ex.printStackTrace(writer); System.err.println(sw); @@ -1642,14 +1643,20 @@ private static > C hopExecutorIfAtCfDelayerThread if (!atCfDelayerThread()) completeCf(ret, v, ex); else delayedExecutor(0, TimeUnit.SECONDS, asyncExecutor) .execute(() -> completeCf(ret, v, ex)); - }); + }).exceptionally(ex -> reportException("Exception occurred in the input cf whenComplete of hop executor:", ex)); return (C) ret; } private static void completeCf(CompletableFuture cf, Object value, @Nullable Throwable ex) { - if (ex == null) cf.complete(value); - else cf.completeExceptionally(ex); + try { + if (ex == null) cf.complete(value); + else cf.completeExceptionally(ex); + } catch (Throwable t) { + if (ex != null) t.addSuppressed(ex); + reportException("Exception occurred in completeCf:", t); + throw t; // rethrow exception, report to caller + } } //# Advanced methods of CompletionStage