FINERACT-2304: Fix auditing of failed batch request while enclosing transaction got enabled
This commit is contained in:
committed by
Arnold Gálovics
parent
c09f620324
commit
96eb744592
+19
@@ -53,6 +53,8 @@ import org.apache.fineract.batch.exception.BatchReferenceInvalidException;
|
||||
import org.apache.fineract.batch.exception.ErrorInfo;
|
||||
import org.apache.fineract.batch.service.ResolutionHelper.BatchRequestNode;
|
||||
import org.apache.fineract.commands.configuration.RetryConfigurationAssembler;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
import org.apache.fineract.commands.service.CommandSourceService;
|
||||
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
||||
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||
import org.apache.fineract.infrastructure.core.filters.BatchCallHandler;
|
||||
@@ -94,6 +96,8 @@ public class BatchApiServiceImpl implements BatchApiService {
|
||||
|
||||
private final RetryConfigurationAssembler retryConfigurationAssembler;
|
||||
|
||||
private final CommandSourceService commandSourceService;
|
||||
|
||||
private EntityManager entityManager;
|
||||
|
||||
/**
|
||||
@@ -166,9 +170,11 @@ public class BatchApiServiceImpl implements BatchApiService {
|
||||
try {
|
||||
return retryingBatch.get();
|
||||
} catch (TransactionException | NonTransientDataAccessException ex) {
|
||||
saveFailedCommandSourceEntries(ex);
|
||||
return buildErrorResponses(ex, responseList);
|
||||
} catch (BatchExecutionException ex) {
|
||||
log.error("Exception during the batch request processing", ex);
|
||||
saveFailedCommandSourceEntries(ex.getCause());
|
||||
responseList.add(buildErrorResponse(ex.getCause(), ex.getRequest()));
|
||||
return responseList;
|
||||
}
|
||||
@@ -395,4 +401,17 @@ public class BatchApiServiceImpl implements BatchApiService {
|
||||
public void setEntityManager(EntityManager entityManager) {
|
||||
this.entityManager = entityManager;
|
||||
}
|
||||
|
||||
private void saveFailedCommandSourceEntries(final Throwable ex) {
|
||||
try {
|
||||
final List<CommandSource> commandSources = BatchRequestContextHolder.getCommandSources();
|
||||
if (!commandSources.isEmpty()) {
|
||||
final String errorMessage = ex != null ? ex.getMessage() : "Batch processing failed";
|
||||
log.debug("Saving {} failed entries for batch audit with error: {}", commandSources.size(), errorMessage);
|
||||
commandSourceService.saveFailedCommandSourcesNewTransaction(commandSources);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to save failed CommandSource entries for batch audit", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -34,7 +34,8 @@ public enum CommandProcessingResultType {
|
||||
AWAITING_APPROVAL(2, "commandProcessingResultType.awaiting.approval"), //
|
||||
REJECTED(3, "commandProcessingResultType.rejected"), //
|
||||
UNDER_PROCESSING(4, "commandProcessingResultType.underProcessing"), //
|
||||
ERROR(5, "commandProcessingResultType.error");
|
||||
ERROR(5, "commandProcessingResultType.error"), //
|
||||
ROLLBACK(6, "commandProcessingResultType.rollback");
|
||||
|
||||
private static final Map<Integer, CommandProcessingResultType> BY_ID = Arrays.stream(values())
|
||||
.collect(Collectors.toMap(CommandProcessingResultType::getValue, v -> v));
|
||||
|
||||
+12
-8
@@ -22,9 +22,11 @@ import static org.apache.fineract.commands.domain.CommandProcessingResultType.UN
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.batch.exception.ErrorInfo;
|
||||
import org.apache.fineract.commands.domain.CommandProcessingResultType;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
@@ -69,12 +71,6 @@ public class CommandSourceService {
|
||||
return saveInitial(wrapper, jsonCommand, maker, idempotencyKey);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
public CommandSource saveInitialSameTransaction(CommandWrapper wrapper, JsonCommand jsonCommand, AppUser maker, String idempotencyKey) {
|
||||
return saveInitial(wrapper, jsonCommand, maker, idempotencyKey);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private CommandSource saveInitial(CommandWrapper wrapper, JsonCommand jsonCommand, AppUser maker, String idempotencyKey) {
|
||||
try {
|
||||
@@ -90,8 +86,8 @@ public class CommandSourceService {
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ)
|
||||
public CommandSource saveResultNewTransaction(@NonNull CommandSource commandSource) {
|
||||
return saveResult(commandSource);
|
||||
public void saveResultNewTransaction(@NonNull CommandSource commandSource) {
|
||||
saveResult(commandSource);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRED)
|
||||
@@ -108,6 +104,14 @@ public class CommandSourceService {
|
||||
return errorHandler.handle(ErrorHandler.getMappable(t));
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void saveFailedCommandSourcesNewTransaction(final List<CommandSource> commandSources) {
|
||||
commandSources.forEach(commandSource -> {
|
||||
commandSource.setStatus(CommandProcessingResultType.ROLLBACK);
|
||||
commandSourceRepository.saveAndFlush(commandSource);
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public CommandSource getCommandSource(Long commandSourceId) {
|
||||
return commandSourceRepository.findById(commandSourceId).orElseThrow(() -> new CommandNotFoundException(commandSourceId));
|
||||
|
||||
+4
@@ -132,6 +132,10 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
storeCommandIdInContext(commandSource); // Store command id as a request attribute
|
||||
}
|
||||
|
||||
if (isEnclosingTransaction) {
|
||||
BatchRequestContextHolder.addCommandSource(commandSource);
|
||||
}
|
||||
|
||||
setIdempotencyKeyStoreFlag(true);
|
||||
|
||||
return executeCommand(wrapper, command, isApprovedByChecker, commandSource, user, isEnclosingTransaction);
|
||||
|
||||
+17
@@ -18,8 +18,11 @@
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
||||
public final class BatchRequestContextHolder {
|
||||
@@ -32,6 +35,8 @@ public final class BatchRequestContextHolder {
|
||||
|
||||
private static final ThreadLocal<Boolean> isEnclosingTransaction = new ThreadLocal<>();
|
||||
|
||||
private static final ThreadLocal<List<CommandSource>> commandSources = ThreadLocal.withInitial(ArrayList::new);
|
||||
|
||||
/**
|
||||
* True if the batch attributes are set
|
||||
*
|
||||
@@ -87,6 +92,7 @@ public final class BatchRequestContextHolder {
|
||||
|
||||
public static void resetIsEnclosingTransaction() {
|
||||
isEnclosingTransaction.remove();
|
||||
commandSources.get().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,4 +136,15 @@ public final class BatchRequestContextHolder {
|
||||
public static void resetTransaction() {
|
||||
batchTransaction.set(Optional.empty());
|
||||
}
|
||||
|
||||
public static void addCommandSource(final CommandSource commandSource) {
|
||||
if (isEnclosingTransaction() && commandSource != null) {
|
||||
commandSources.get().add(commandSource);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<CommandSource> getCommandSources() {
|
||||
return new ArrayList<>(commandSources.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user