package com.ard.work.config;
|
|
import com.ard.work.domain.enums.RouteEvent;
|
import com.ard.work.domain.enums.RouteState;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.messaging.Message;
|
import org.springframework.messaging.support.MessageBuilder;
|
import org.springframework.statemachine.StateMachine;
|
import org.springframework.statemachine.service.StateMachineService;
|
import org.springframework.statemachine.support.DefaultExtendedState;
|
import org.springframework.statemachine.support.DefaultStateMachineContext;
|
import org.springframework.stereotype.Service;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
@Service
|
@RequiredArgsConstructor
|
public class RouteStateMachineService {
|
|
private final StateMachineService<RouteState, RouteEvent> stateMachineService;
|
private final RouteStateMachineListener listener;
|
private final ConcurrentHashMap<String, Boolean> listenerRegisteredMap = new ConcurrentHashMap<>();
|
|
private StateMachine<RouteState, RouteEvent> getStateMachine(String boxSn) {
|
StateMachine<RouteState, RouteEvent> stateMachine =
|
stateMachineService.acquireStateMachine(boxSn);
|
|
// 使用原子操作确保 listener 只添加一次
|
listenerRegisteredMap.computeIfAbsent(boxSn, k -> {
|
stateMachine.addStateListener(listener);
|
return true;
|
});
|
stateMachine.start();
|
return stateMachine;
|
}
|
|
/**
|
* 发送事件到指定boxSn的状态机
|
*/
|
public boolean sendEvent(String boxSn, RouteEvent event) {
|
try {
|
// 获取/创建指定boxSn的状态机实例
|
StateMachine<RouteState, RouteEvent> stateMachine = getStateMachine(boxSn);
|
|
// 构建事件消息(携带boxSn作为头信息)
|
Message<RouteEvent> message = MessageBuilder
|
.withPayload(event)
|
.setHeader("boxSn", boxSn)
|
.build();
|
|
// 发送事件并返回执行结果
|
return stateMachine.sendEvent(message);
|
} catch (Exception e) {
|
// 异常处理:日志记录、状态机重置等
|
throw new RuntimeException("发送航线状态事件失败,boxSn=" + boxSn + ", event=" + event, e);
|
}
|
}
|
|
/**
|
* 获取指定boxSn的当前状态
|
*/
|
public RouteState getCurrentState(String boxSn) {
|
try {
|
StateMachine<RouteState, RouteEvent> stateMachine =
|
stateMachineService.acquireStateMachine(boxSn);
|
return stateMachine.getState().getId();
|
} catch (Exception e) {
|
// 未找到状态机实例时返回初始状态
|
return RouteState.IDLE;
|
}
|
}
|
|
/**
|
* 释放指定boxSn的状态机实例(可选,节省资源)
|
*/
|
public void releaseStateMachine(String boxSn) {
|
stateMachineService.releaseStateMachine(boxSn);
|
}
|
|
/**
|
* 重置指定boxSn的状态机(恢复到初始状态)
|
*/
|
public void resetStateMachine(String boxSn) {
|
try {
|
StateMachine<RouteState, RouteEvent> stateMachine =
|
stateMachineService.acquireStateMachine(boxSn);
|
|
// 1️⃣ 停止状态机
|
stateMachine.stop();
|
|
// 2️⃣ 构造 ExtendedState(可选,但强烈推荐)
|
DefaultExtendedState extendedState = new DefaultExtendedState();
|
extendedState.getVariables().put("boxSn", boxSn);
|
|
// 3️⃣ 重置状态机到 IDLE
|
stateMachine.getStateMachineAccessor()
|
.doWithAllRegions(accessor -> {
|
accessor.resetStateMachine(
|
new DefaultStateMachineContext<>(
|
RouteState.IDLE, // 初始状态
|
null, // event
|
null, // event headers
|
extendedState // 扩展状态
|
)
|
);
|
});
|
|
// 4️⃣ 重新启动
|
stateMachine.start();
|
|
} catch (Exception e) {
|
throw new RuntimeException("重置航线状态机失败,boxSn=" + boxSn, e);
|
}
|
}
|
}
|