private void processActions(String sagaId, SagaInstance sagaInstance, Data sagaData, SagaActions<Data> actions) { String lastRequestId = sagaCommandProducer.sendCommands(this.getSagaType(), sagaId, actions.getCommands(), this.makeSagaReplyChannel()); sagaInstance.setLastRequestId(lastRequestId); actions.getUpdatedState().ifPresent(sagaInstance::setStateName); sagaInstance.setSerializedSagaData(SagaDataSerde.serializeSagaData(actions.getUpdatedSagaData().orElse(sagaData))); if (actions.isEndState()) { performEndStateActions(sagaId, sagaInstance, actions.isCompensating(), sagaData); } sagaInstanceRepository.update(sagaInstance); }
public SagaActions<Data> build() { return new SagaActions<>(commands, updatedSagaData, updatedState, endState, compensating); }
@Override public SagaInstance create(Data sagaData, Optional<String> resource) { SagaInstance sagaInstance = new SagaInstance(getSagaType(), null, "????", null, SagaDataSerde.serializeSagaData(sagaData), new HashSet<>()); sagaInstanceRepository.save(sagaInstance); String sagaId = sagaInstance.getId(); resource.ifPresent( r -> Assert.isTrue(sagaLockManager.claimLock(getSagaType(), sagaId, r), "Cannot claim lock for resource")); SagaActions<Data> actions = getStateDefinition().getStartingHandler().get().apply(sagaData); List<CommandWithDestination> commands = actions.getCommands(); sagaData = actions.getUpdatedSagaData().orElse(sagaData); sagaInstance.setLastRequestId(sendCommands(sagaId, commands)); sagaInstance.setSerializedSagaData(SagaDataSerde.serializeSagaData(sagaData)); publishEvents(sagaId, actions.getEventsToPublish(), actions.getUpdatedState()); Optional<String> possibleNewState = actions.getUpdatedState(); maybeUpdateState(sagaInstance, possibleNewState); maybePerformEndStateActions(sagaId, sagaInstance, possibleNewState); sagaInstanceRepository.update(sagaInstance); updateEnlistedAggregates(sagaId, actions.getEnlistedAggregates()); updateEventInstanceSubscriptions(sagaData, sagaId, sagaInstance.getStateName()); return sagaInstance; }
@Override public RawSagaStateMachineAction getReplyHandler() { return (rawSagaData, reply) -> { possibleReplyHandler.ifPresent(handler -> handler.accept(data, reply)); if (stepsToExecute.isEmpty()) { return SagaActions.builder() .withUpdatedState(encodeState(SagaExecutionState.makeEndState())) .withIsEndState(true) .withIsCompensating(state.isCompensating()) .build(); } else { // do something return makeSagaActions(data, stepsToExecute, state, state.nextState(stepsToExecute.size())); } }; }
private void handleReply(Message message) { if (!isReplyForThisSagaType(message)) return; logger.debug("Handle reply: {}", message); String sagaId = message.getRequiredHeader(SagaReplyHeaders.REPLY_SAGA_ID); String sagaType = message.getRequiredHeader(SagaReplyHeaders.REPLY_SAGA_TYPE); SagaInstance sagaInstance = sagaInstanceRepository.find(sagaType, sagaId); Data sagaData = SagaDataSerde.deserializeSagaData(sagaInstance.getSerializedSagaData()); message.getHeader(SagaReplyHeaders.REPLY_LOCKED).ifPresent(lockedTarget -> { String destination = message.getRequiredHeader(CommandMessageHeaders.inReply(CommandMessageHeaders.DESTINATION)); sagaInstance.addDestinationsAndResources(singleton(new DestinationAndResource(destination, lockedTarget))); }); String currentState = sagaInstance.getStateName(); logger.info("Current state={}", currentState); SagaActions<Data> actions = getStateDefinition().handleReply(currentState, sagaData, message); logger.info("Handled reply. Sending commands {}", actions.getCommands()); processActions(sagaId, sagaInstance, sagaData, actions); }
List<CommandWithDestination> commands = actions.getCommands(); sagaData = actions.getUpdatedSagaData().orElse(sagaData); publishEvents(sagaId, actions.getEventsToPublish(), actions.getUpdatedState()); Optional<String> possibleNewState = actions.getUpdatedState(); maybeUpdateState(sagaInstance, possibleNewState); maybePerformEndStateActions(sagaId, sagaInstance, possibleNewState); updateEnlistedAggregates(sagaId, actions.getEnlistedAggregates()); sagaInstance.setLastRequestId(sendCommands(sagaId, commands)); updateEventInstanceSubscriptions(sagaData, sagaId, sagaInstance.getStateName());
@Override public RawSagaStateMachineAction getReplyHandler() { return (rawSagaData, reply) -> { possibleReplyHandler.ifPresent(handler -> handler.accept(data, reply)); if (stepsToExecute.isEmpty()) { return SagaActions.builder() .withUpdatedState(encodeState(SagaExecutionState.makeEndState())) .withIsEndState(true) .withIsCompensating(state.isCompensating()) .build(); } else { // do something return makeSagaActions(data, stepsToExecute, state, state.nextState(stepsToExecute.size())); } }; }
private SagaActions<TestSagaData> makeFirstSagaActions() { return SagaActions.<TestSagaData>builder() .withUpdatedSagaData(sagaDataUpdatedByStartingHandler) .withCommand(commandForParticipant1).withUpdatedState("state-A").build(); }
private SagaActions makeSagaActions(final Data data, final StepsToExecute<Data> stepsToExecute, SagaExecutionState currentState, SagaExecutionState newState) { stepsToExecute.executeLocalSteps(data, currentState.isCompensating()); // TODO What to do if the above fails return SagaActions.builder() .withCommands(stepsToExecute.makeCommandsToSend(data, currentState.isCompensating())) .withUpdatedSagaData(data) .withUpdatedState(encodeState(newState)) .withIsEndState(newState.isEndState()) .withIsCompensating(currentState.isCompensating()) .build(); }
private SagaActions<TestSagaData> makeSecondSagaActions(boolean compensating) { return SagaActions.<TestSagaData>builder() .withCommand(commandForParticipant2) .withUpdatedState("state-B") .withUpdatedSagaData(sagaDataUpdatedByReplyHandler) .withIsEndState(true) .withIsCompensating(compensating) .build(); }
private SagaActions makeSagaActions(final Data data, final StepsToExecute<Data> stepsToExecute, SagaExecutionState currentState, SagaExecutionState newState) { stepsToExecute.executeLocalSteps(data, currentState.isCompensating()); // TODO What to do if the above fails return SagaActions.builder() .withCommands(stepsToExecute.makeCommandsToSend(data, currentState.isCompensating())) .withUpdatedSagaData(data) .withUpdatedState(encodeState(newState)) .withIsEndState(newState.isEndState()) .withIsCompensating(currentState.isCompensating()) .build(); }