EventualConsistencyTransactionSupport.java
package io.vanillabp.integration.runtime.processservice;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import jakarta.annotation.PreDestroy;
import jakarta.inject.Inject;
import jakarta.transaction.Status;
import jakarta.transaction.TransactionManager;
import jakarta.transaction.TransactionScoped;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@TransactionScoped
@Slf4j
public class EventualConsistencyTransactionSupport {
@Getter
@RequiredArgsConstructor
public class ToDo {
Object context;
final Supplier<Object> onCommitProbe;
final Supplier<String> commitProbeDescription;
final Consumer<Object> afterCommitAction;
final Supplier<String> commitActionDescription;
}
@Inject
TransactionManager transactionManager;
List<ToDo> toDos = new LinkedList<>();
public void addProbeAndAction(
final Supplier<Object> onCommitProbe,
final Supplier<String> commitProbeDescription,
final Consumer<Object> afterCommitAction,
final Supplier<String> commitActionDescription) {
toDos.add(new ToDo(
onCommitProbe, commitProbeDescription, afterCommitAction, commitActionDescription));
}
@PreDestroy
void onBeforeEndTransaction() throws Exception {
// if transaction is rolled back, then we don't need to do anything
if (transactionManager.getStatus() != Status.STATUS_ACTIVE) {
return;
}
Supplier<String> commitProbeDescription = null;
try {
for (final ToDo toDo : toDos) {
if (log.isTraceEnabled()) {
log.trace("Doing pre-commit probe for '{}'", toDo.commitProbeDescription.get());
}
commitProbeDescription = toDo.commitProbeDescription;
toDo.context = toDo.onCommitProbe.get();
}
} catch (Exception e) {
log.error("Will rollback because pre-commit testing failed for '{}'",
commitProbeDescription == null ? "unknown" : commitProbeDescription.get());
transactionManager.setRollbackOnly();
}
}
}