package com.zy.core.move; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.zy.common.utils.RedisUtil; import com.zy.core.enums.RedisKeyType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import java.util.Objects; @Component public class StationMoveSessionRegistry { private static final int SESSION_EXPIRE_SECONDS = 60 * 60 * 24; @Autowired private RedisUtil redisUtil; public synchronized StationMoveSession load(Integer taskNo) { if (taskNo == null || taskNo <= 0 || redisUtil == null) { return null; } Object sessionObj = redisUtil.get(buildKey(taskNo)); if (sessionObj == null) { return null; } try { return JSON.parseObject(String.valueOf(sessionObj), StationMoveSession.class); } catch (Exception ignore) { return null; } } public synchronized void save(StationMoveSession session) { if (session == null || session.getTaskNo() == null || session.getTaskNo() <= 0 || redisUtil == null) { return; } long now = System.currentTimeMillis(); if (session.getCreatedAt() == null || session.getCreatedAt() <= 0L) { session.setCreatedAt(now); } session.setUpdatedAt(now); redisUtil.set(buildKey(session.getTaskNo()), JSON.toJSONString(session, SerializerFeature.DisableCircularReferenceDetect), SESSION_EXPIRE_SECONDS); } public synchronized void delete(Integer taskNo) { if (taskNo == null || taskNo <= 0 || redisUtil == null) { return; } redisUtil.del(buildKey(taskNo)); } public synchronized boolean isActiveRoute(Integer taskNo, Integer routeVersion) { StationMoveSession session = load(taskNo); return session != null && session.isActive() && routeVersion != null && Objects.equals(routeVersion, session.getRouteVersion()); } public synchronized boolean shouldSkipOutOrderDecision(Integer taskNo, Integer currentStationId) { StationMoveSession session = load(taskNo); if (session == null || !session.isActive() || currentStationId == null) { return false; } List fullPathStationIds = session.getFullPathStationIds(); if (fullPathStationIds == null || !fullPathStationIds.contains(currentStationId)) { return false; } if (StationMoveDispatchMode.CIRCLE == session.getDispatchMode()) { return true; } return !Objects.equals(currentStationId, session.getCurrentRouteTargetStationId()); } public synchronized boolean isCircleDecisionStation(Integer taskNo, Integer currentStationId) { StationMoveSession session = load(taskNo); return session != null && session.isActive() && StationMoveDispatchMode.CIRCLE == session.getDispatchMode() && currentStationId != null && Objects.equals(currentStationId, session.getNextDecisionStationId()); } public synchronized boolean isCircleTransitStation(Integer taskNo, Integer currentStationId) { StationMoveSession session = load(taskNo); if (session == null || !session.isActive() || StationMoveDispatchMode.CIRCLE != session.getDispatchMode() || currentStationId == null || Objects.equals(currentStationId, session.getNextDecisionStationId())) { return false; } List fullPathStationIds = session.getFullPathStationIds(); return fullPathStationIds != null && fullPathStationIds.contains(currentStationId); } public synchronized StationMoveSession registerPlan(Integer taskNo, String threadImpl, Integer currentStationId, Integer businessTargetStationId, StationMoveTriggerType triggerType, StationMoveDispatchMode dispatchMode, Integer currentRouteTargetStationId, Integer nextDecisionStationId, List fullPathStationIds, boolean cancelActive, String cancelReason) { if (taskNo == null || taskNo <= 0) { return null; } StationMoveSession current = load(taskNo); StationMoveSession next = new StationMoveSession(); next.setTaskNo(taskNo); next.setThreadImpl(threadImpl); next.setRouteVersion(current == null || current.getRouteVersion() == null ? 1 : current.getRouteVersion() + 1); next.setCurrentStationId(currentStationId); next.setBusinessTargetStationId(businessTargetStationId); next.setTriggerType(triggerType); next.setDispatchMode(dispatchMode); next.setCurrentRouteTargetStationId(currentRouteTargetStationId); next.setNextDecisionStationId(nextDecisionStationId); next.setStatus(StationMoveSession.STATUS_WAITING); next.setCancelReason(cancelReason); next.setFullPathStationIds(copyIntegerList(fullPathStationIds)); next.setPathSignature(buildPathSignature(fullPathStationIds)); save(next); return next; } public synchronized boolean isSameActivePath(Integer taskNo, List fullPathStationIds) { StationMoveSession session = load(taskNo); if (session == null || !session.isActive()) { return false; } return Objects.equals(session.getPathSignature(), buildPathSignature(fullPathStationIds)); } public synchronized void markSegmentIssued(Integer taskNo, Integer routeVersion) { StationMoveSession session = load(taskNo); if (session == null || !Objects.equals(session.getRouteVersion(), routeVersion)) { return; } session.setStatus(StationMoveSession.STATUS_RUNNING); session.setLastIssuedAt(System.currentTimeMillis()); save(session); } public synchronized void updateCurrentStation(Integer taskNo, Integer routeVersion, Integer currentStationId) { StationMoveSession session = load(taskNo); if (session == null || !Objects.equals(session.getRouteVersion(), routeVersion)) { return; } session.setCurrentStationId(currentStationId); if (!StationMoveSession.STATUS_CANCEL_PENDING.equals(session.getStatus())) { session.setStatus(StationMoveSession.STATUS_RUNNING); } save(session); } public synchronized void markCancelPending(Integer taskNo, String cancelReason) { StationMoveSession session = load(taskNo); if (session == null || !session.isActive()) { return; } session.setStatus(StationMoveSession.STATUS_CANCEL_PENDING); session.setCancelReason(cancelReason); save(session); } public synchronized void markCancelled(Integer taskNo, Integer routeVersion, Integer currentStationId, String cancelReason) { updateTerminal(taskNo, routeVersion, currentStationId, StationMoveSession.STATUS_CANCELLED, cancelReason); } public synchronized void markBlocked(Integer taskNo, Integer routeVersion, Integer currentStationId) { updateTerminal(taskNo, routeVersion, currentStationId, StationMoveSession.STATUS_BLOCKED, null); } public synchronized void markTimeout(Integer taskNo, Integer routeVersion, Integer currentStationId) { updateTerminal(taskNo, routeVersion, currentStationId, StationMoveSession.STATUS_TIMEOUT, null); } public synchronized void markFinished(Integer taskNo, Integer routeVersion, Integer currentStationId) { updateTerminal(taskNo, routeVersion, currentStationId, StationMoveSession.STATUS_FINISHED, null); } public synchronized StationMoveSession buildCircleSessionCommandSource(Integer taskNo) { StationMoveSession session = load(taskNo); if (session == null || !session.isActive() || StationMoveDispatchMode.CIRCLE != session.getDispatchMode()) { return null; } return session; } private void updateTerminal(Integer taskNo, Integer routeVersion, Integer currentStationId, String status, String cancelReason) { StationMoveSession session = load(taskNo); if (session == null || !Objects.equals(session.getRouteVersion(), routeVersion)) { return; } session.setCurrentStationId(currentStationId); session.setStatus(status); session.setCancelReason(cancelReason); save(session); } private String buildKey(Integer taskNo) { return RedisKeyType.STATION_MOVE_SESSION_.key + taskNo; } private String buildPathSignature(List fullPathStationIds) { if (fullPathStationIds == null || fullPathStationIds.isEmpty()) { return ""; } StringBuilder builder = new StringBuilder(); for (Integer stationId : fullPathStationIds) { if (stationId == null) { continue; } if (builder.length() > 0) { builder.append("->"); } builder.append(stationId); } return builder.toString(); } private List copyIntegerList(List source) { List result = new ArrayList<>(); if (source != null) { result.addAll(source); } return result; } }