This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch release/1.13.1 in repository https://gitbox.apache.org/repos/asf/fineract.git
commit e3096c7ef060484efcc5104e378a8bff17969f29 Author: Adam Saghy <[email protected]> AuthorDate: Tue Oct 21 15:29:09 2025 +0200 FINERACT-2396: Fix retry issue during persisting CommandSource --- .../commands/service/SynchronousCommandProcessingService.java | 8 ++++---- .../commands/service/SynchronousCommandProcessingServiceTest.java | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java index 43647f426a..a13835b626 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java @@ -30,6 +30,7 @@ import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -166,13 +167,12 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer try { CommandSource finalCommandSource = commandSource; + AtomicInteger attemptNumber = new AtomicInteger(0); CommandSource savedCommandSource = persistenceRetry.executeSupplier(() -> { - // Get metrics for logging - long attemptNumber = persistenceRetry.getMetrics().getNumberOfFailedCallsWithRetryAttempt() + 1; - // Critical: Refetch on retry attempts (not on first attempt) CommandSource currentSource = finalCommandSource; - if (attemptNumber > 1) { + attemptNumber.getAndIncrement(); + if (attemptNumber.get() > 1 && commandSource.getId() != null) { log.info("Retrying command result save - attempt {} for command ID {}", attemptNumber, finalCommandSource.getId()); currentSource = commandSourceService.getCommandSource(finalCommandSource.getId()); } diff --git a/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java index 4e71ae7954..7bcb2b7d4f 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/commands/service/SynchronousCommandProcessingServiceTest.java @@ -591,5 +591,11 @@ public class SynchronousCommandProcessingServiceTest { assertEquals(persistentException, exception.getCause()); assertTrue(saveAttempts.get() >= 3, "Expected at least 3 save attempts, but got: " + saveAttempts.get()); + // First call was before saving CommandSource, then 2 calls during retry (1st retry does not try to fetch it) + verify(commandSourceService, times(3)).getCommandSource(commandId); + // Let test whether consecutive calls does not try to refetch immediately + when(commandSourceService.saveResultSameTransaction(any(CommandSource.class))).thenReturn(commandSource); + underTest.executeCommand(commandWrapper, jsonCommand, false); + verify(commandSourceService, times(4)).getCommandSource(commandId); } }
