diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/SecondaryAuctionT0SessionStateMachineConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/SecondaryAuctionT0SessionStateMachineConfig.java index ef3a879b8..3477df9ca 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/SecondaryAuctionT0SessionStateMachineConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/SecondaryAuctionT0SessionStateMachineConfig.java @@ -157,6 +157,8 @@ public class SecondaryAuctionT0SessionStateMachineConfig TaskType.FinishingSession, TaskType.PSEUDO_waitSdfAfterPaymentInstructions, TaskType.PSEUDO_waitAfterObligationAdmissionError, + TaskType.PSEUDO_waitAfterObligationAdmissionRestore, + TaskType.PSEUDO_waitAfterInspectionRestore, TaskType.PSEUDO_waitSdfAfterAgainRevise, TaskType.PSEUDO_waitAfterInspectionError ))) @@ -189,8 +191,8 @@ public class SecondaryAuctionT0SessionStateMachineConfig .action(inspectionObligationsV2Action); sourceObligationAdmission(transitions); - sourcePseudoAfterOAError(transitions); - sourcePseudoAfterIOError(transitions); + sourcePseudoAfterOAPause(transitions); + sourcePseudoAfterIOPause(transitions); sourceFormingPaymentInstruction(transitions); sourcePseudoWaitSdfAfterPaymentInstructions(transitions); sourceAgainRevise(transitions); @@ -227,21 +229,22 @@ public class SecondaryAuctionT0SessionStateMachineConfig .action(formingPaymentInstructionAssetsAction); } - private void sourcePseudoAfterOAError(StateMachineTransitionConfigurer transitions) throws Exception { + private void sourcePseudoAfterOAPause(StateMachineTransitionConfigurer transitions) throws Exception { transitions //continue and repeat after ObligationAdmission .withExternal() .source(TaskType.PSEUDO_waitAfterObligationAdmissionError).target(TaskType.InclusionToPool) .action(chain(activeWsAction, obligationAdmissionContinueAction, inclusionToPoolAction)) - .event(SsnEvent.CONTINUE) - .and() - .withExternal() - .source(TaskType.PSEUDO_waitAfterObligationAdmissionError).target(TaskType.ObligationsAdmission) + .event(SsnEvent.CONTINUE); + for (var taskType : List.of(TaskType.PSEUDO_waitAfterObligationAdmissionError, TaskType.PSEUDO_waitAfterObligationAdmissionRestore)) { + transitions.withExternal() + .source(taskType).target(TaskType.ObligationsAdmission) .action(chain(activeWsAction, discardOblAdmStash, obligationAdmissionAction)) .event(SsnEvent.REPEAT); + } } - private void sourcePseudoAfterIOError(StateMachineTransitionConfigurer transitions) throws Exception { + private void sourcePseudoAfterIOPause(StateMachineTransitionConfigurer transitions) throws Exception { transitions //continue and repeat after InspectionObligations .withExternal() @@ -249,12 +252,13 @@ public class SecondaryAuctionT0SessionStateMachineConfig .action(activeWsAction) .action(saveRegistriesAfterInspectionAndContinueAction) .action(formingPaymentInstructionAssetsAction) - .event(SsnEvent.CONTINUE) - .and() - .withExternal() - .source(TaskType.PSEUDO_waitAfterInspectionError).target(TaskType.InspectionObligations) + .event(SsnEvent.CONTINUE); + for (var taskType : List.of(TaskType.PSEUDO_waitAfterInspectionError, TaskType.PSEUDO_waitAfterInspectionRestore)) { + transitions.withExternal() + .source(taskType).target(TaskType.InspectionObligations) .action(chain(activeWsAction, discardInspOblStash, inspectionObligationsV2Action)) .event(SsnEvent.REPEAT); + } } private void sourceFormingPaymentInstruction(StateMachineTransitionConfigurer transitions) throws Exception { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java index d8941c050..2d9a4e3c9 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java @@ -59,7 +59,9 @@ public enum TaskType implements IEnumKey { PSEUDO_waitSdfAfterPaymentInstructions("PSEUDO_waitSdfAfterPaymentInstructions"), PSEUDO_waitSdfAfterAgainRevise("PSEUDO_waitSdfAfterAgainRevise"), PSEUDO_waitAfterObligationAdmissionError("PSEUDO_waitAfterObligationAdmissionError"), + PSEUDO_waitAfterObligationAdmissionRestore("PSEUDO_waitAfterObligationAdmissionRestore"), PSEUDO_waitAfterInspectionError("PSEUDO_waitAfterInspectionError"), + PSEUDO_waitAfterInspectionRestore("PSEUDO_waitAfterInspectionRestore"), PSEUDO_waitAfterInspectionDepositReturnError("PSEUDO_waitAfterInspectionDepositReturnError"), PSEUDO_InspectionObligationDepositReturn("PSEUDO_InspectionObligationDepositReturn"), PSEUDO_end("PSEUDO_end"), diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/RestoreSessionService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/RestoreSessionService.java new file mode 100644 index 000000000..29dcdf616 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/RestoreSessionService.java @@ -0,0 +1,68 @@ +package ru.spcex.clearing.session.state.factory; + +import java.util.Map; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.StateMachineFactory; +import org.springframework.statemachine.support.DefaultExtendedState; +import org.springframework.statemachine.support.DefaultStateMachineContext; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.misc.Session; +import ru.spcex.clearing.session.stage.TaskType; +import ru.spcex.clearing.session.state.DataEnum; +import ru.spcex.clearing.session.state.SsnEvent; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionType; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +@Component +public class RestoreSessionService { + + public StateMachine restore(StateMachineFactory stateMachineFactory, Session session) { + StateMachine sm = stateMachineFactory.getStateMachine(); + sm.stop(); + + TaskType status = validatedStatus(session); + SessionType sessionType = IEnumKey.getEnumByKey(SessionType.class, session.getSessionType()); + Section section = IEnumKey.getEnumByKey(Section.class, session.getSection()); + + DefaultExtendedState state = new DefaultExtendedState(); + Map vars = state.getVariables(); + vars.put(DataEnum.session, session); + vars.put(DataEnum.sessionId, session.getId()); + vars.put(DataEnum.sessionType, sessionType); + vars.put(DataEnum.section, section); + //fixme DataEnum.counterPartyId??? + TaskType restoredState; + switch (status) { + case ObligationsAdmission -> restoredState = TaskType.PSEUDO_waitAfterObligationAdmissionRestore; + case InspectionObligations -> restoredState = TaskType.PSEUDO_waitAfterInspectionRestore; + default -> throw new IllegalStateException( + "Unexpected value: session.id=%d status %s".formatted(session.getId(), status) + ); + } + + DefaultStateMachineContext ctx = new DefaultStateMachineContext<>( + restoredState, + null, + null, + state + ); + + sm.getStateMachineAccessor().doWithAllRegions(a -> a.resetStateMachine(ctx)); + sm.start(); + return sm; + } + + private TaskType validatedStatus(Session session) { + TaskType status = IEnumKey.getEnumByKey(TaskType.class, session.getSessionStatus()); + boolean statusOk = IEnumKey.contains(status, + TaskType.ObligationsAdmission, + TaskType.InspectionObligations); + if (!statusOk) { + throw new IllegalStateException( + "cannot restore session %d for status %s".formatted(session.getId(), session.getSessionStatus()) + ); + } + return status; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/SessionStateMachineWrapper.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/SessionStateMachineWrapper.java index 79d27e788..25a60d371 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/SessionStateMachineWrapper.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/factory/SessionStateMachineWrapper.java @@ -45,6 +45,7 @@ public class SessionStateMachineWrapper { private final Imdg ssnImdg; private final NotificationSender notification; private final IMessageResolver msgs; + private final RestoreSessionService restoreSessionService; @Autowired public SessionStateMachineWrapper( @@ -52,7 +53,7 @@ public class SessionStateMachineWrapper { Map> factories, SessionStatusChangingInterceptor statusChangingInterceptor, NotificationSender notification, - IMessageResolver msgs + IMessageResolver msgs, RestoreSessionService restoreSessionService ) { this.factories = factories .entrySet() @@ -67,6 +68,7 @@ public class SessionStateMachineWrapper { this.ssnImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); this.notification = notification; this.msgs = msgs; + this.restoreSessionService = restoreSessionService; } public synchronized void defineAndStartSession(BaseRequest r) throws ValidationException { @@ -142,7 +144,13 @@ public class SessionStateMachineWrapper { private StateMachine build( StateMachineFactory stateMachineFactory ) { - StateMachine stateMachine = stateMachineFactory.getStateMachine(); + Session session = getPausedSession().orElse(null); + StateMachine stateMachine; + if (session != null) { + stateMachine = restoreSessionService.restore(stateMachineFactory, session); + } else { + stateMachine = stateMachineFactory.getStateMachine(); + } stateMachine .getStateMachineAccessor() .doWithAllRegions( @@ -156,7 +164,16 @@ public class SessionStateMachineWrapper { ImdgPredicateBuilder pb = ssnImdg.predicateBuilder(); Session existActiveSession = ssnImdg.getSingleObjectByPredicate( pb.or( - pb.equals("workflowStatus", WorkflowStatus.Active.getKey()), + pb.equals("workflowStatus", WorkflowStatus.Active.getKey()) + ) + ); + return Optional.ofNullable(existActiveSession); + } + + private Optional getPausedSession() { + ImdgPredicateBuilder pb = ssnImdg.predicateBuilder(); + Session existActiveSession = ssnImdg.getSingleObjectByPredicate( + pb.or( pb.equals("workflowStatus", WorkflowStatus.Pause.getKey()) ) );