Я думаю использовать действия перехода, чтобы убедиться, что правила конечного автомата соблюдаются, т. е. мне нужно получить объект из другой службы с помощью REST API, вызвать эту службу REST API для обновления состояния объекта. Если каким-то образом служба недоступна/возвращает 500, конечный автомат моего приложения должен выйти из строя и действия перехода не должны выполняться.
Согласно ChatGPT, это порядок действий с использованием конечного автомата:
- перехватчик preEvent
- перехватчик preStateChange
- действия перехода
- действия выхода из состояния
- действия входа в состояние
- перехватчик postStateChange
- переход слушателя
Код: Выделить всё
@Service
@RequiredArgsConstructor
public class ObjectStateMachineFactory {
private final StateMachineFactory factory;
private final UpdateObjectStateInterceptor updateObjectStateInterceptor;
public StateMachine getStateMachine() {
StateMachine sm = factory.getStateMachine();
sm.getStateMachineAccessor()
.doWithAllRegions(
access -> access.addStateMachineInterceptor(updateObjectStateInterceptor));
return sm;
}
}
@Slf4j
@Service
@RequiredArgsConstructor
public class ObjectStateMachineService {
private final ObjectStateMachineFactory stateMachineFactory;
private final ObjectService objectService;
private final UpdateObjectInterceptor updateObjectInterceptor;
@Transactional
public boolean processObjectEvent(String id, ObjectEvent event) {
CustomObject obj = objectService.getObject(id);
// TODO: Don't build state machine everytime as its an expensive operation
StateMachine sm = stateMachineFactory.getStateMachine();
try {
sm.startReactively();
// Set initial state using resetStateMachine
CustomObjectState currentState =
CustomObjectState.fromValue(obj.getState().getObj().getKey());
if (sm.getState() == null || sm.getState().getId() != currentState) {
sm.getStateMachineAccessor()
.withRegion()
.resetStateMachineReactively(
new DefaultStateMachineContext(currentState, null, null, sm.getExtendedState()))
.block();
}
sm.getExtendedState().getVariables().put("customObj", obj);
boolean success = sm.sendEvent(event);
}
return success;
} finally {
sm.stop();
}
}
}
@Slf4j
@Configuration
@RequiredArgsConstructor
@EnableStateMachineFactory
public class OrderStateConfig extends StateMachineConfigurerAdapter {
@Override
public void configure(StateMachineStateConfigurer states)
throws Exception {
states
.withStates()
.initial(CustomObjectState.UNCONFIRMED)
.states(EnumSet.allOf(CustomObjectState.class));
}
@Override
public void configure(StateMachineConfigurationConfigurer config)
throws Exception {
// IMPORTANT: disable auto-start so interceptor can be attached first
config.withConfiguration().autoStartup(false);
}
@Override
public void configure(StateMachineTransitionConfigurer transitions)
throws Exception {
transitions
// CONFIRM event
.withExternal()
.source(CustomObjectState.A)
.target(CustomObjectState.B)
.event(ObjectEvent.CONFIRM)
.guard(objectStateGuard.canTransitToB())
.action(sendNotificationAction)
.
.
.
objectStateGuard.canTransitToB();
UpdateObjectStateInterceptor.preStateChange();
sendNotificationAction
но sendNotificationAction происходит до preStateChange
есть ли способ выполните это, или я использую неправильную функцию конечного автомата? как использовать конечный автомат без локальной базы данных? спасибо
Подробнее здесь: https://stackoverflow.com/questions/798 ... te-machine
Мобильная версия