restore session state machine example

This commit is contained in:
ialbert 2025-07-28 12:55:17 +03:00
parent dc8a07b143
commit ae3e2a7571
4 changed files with 106 additions and 15 deletions

View file

@ -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<TaskType, SsnEvent> transitions) throws Exception {
private void sourcePseudoAfterOAPause(StateMachineTransitionConfigurer<TaskType, SsnEvent> 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<TaskType, SsnEvent> transitions) throws Exception {
private void sourcePseudoAfterIOPause(StateMachineTransitionConfigurer<TaskType, SsnEvent> 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<TaskType, SsnEvent> transitions) throws Exception {

View file

@ -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"),

View file

@ -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<TaskType, SsnEvent> restore(StateMachineFactory<TaskType, SsnEvent> stateMachineFactory, Session session) {
StateMachine<TaskType, SsnEvent> 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<Object, Object> 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<TaskType, SsnEvent> 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;
}
}

View file

@ -45,6 +45,7 @@ public class SessionStateMachineWrapper {
private final Imdg<Session> ssnImdg;
private final NotificationSender notification;
private final IMessageResolver msgs;
private final RestoreSessionService restoreSessionService;
@Autowired
public SessionStateMachineWrapper(
@ -52,7 +53,7 @@ public class SessionStateMachineWrapper {
Map<String, StateMachineFactory<TaskType, SsnEvent>> 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<LauncherCommandRequest> r) throws ValidationException {
@ -142,7 +144,13 @@ public class SessionStateMachineWrapper {
private StateMachine<TaskType, SsnEvent> build(
StateMachineFactory<TaskType, SsnEvent> stateMachineFactory
) {
StateMachine<TaskType, SsnEvent> stateMachine = stateMachineFactory.getStateMachine();
Session session = getPausedSession().orElse(null);
StateMachine<TaskType, SsnEvent> 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<Session> getPausedSession() {
ImdgPredicateBuilder pb = ssnImdg.predicateBuilder();
Session existActiveSession = ssnImdg.getSingleObjectByPredicate(
pb.or(
pb.equals("workflowStatus", WorkflowStatus.Pause.getKey())
)
);