package com.zy.core.utils.station;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.core.common.Cools;
|
import com.zy.asrs.entity.BasStationOpt;
|
import com.zy.asrs.service.BasStationOptService;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.core.enums.RedisKeyType;
|
import com.zy.core.enums.StationCommandType;
|
import com.zy.core.model.command.StationCommand;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Objects;
|
|
@Component
|
public class StationDispatchRuntimeStateSupport {
|
private static final int STATION_IDLE_TRACK_EXPIRE_SECONDS = 60 * 60;
|
private static final String IDLE_RECOVER_CLEARED_MEMO = "idleRecoverRerouteCleared";
|
|
@Autowired
|
private RedisUtil redisUtil;
|
@Autowired
|
private BasStationOptService basStationOptService;
|
|
public StationTaskIdleTrack touchIdleTrack(Integer taskNo, Integer stationId) {
|
if (taskNo == null || taskNo <= 0 || stationId == null) {
|
return null;
|
}
|
long now = System.currentTimeMillis();
|
StationTaskIdleTrack idleTrack = loadIdleTrack(taskNo);
|
if (idleTrack == null || !Objects.equals(idleTrack.getStationId(), stationId)) {
|
idleTrack = new StationTaskIdleTrack(taskNo, stationId, now);
|
saveIdleTrack(idleTrack);
|
}
|
return idleTrack;
|
}
|
|
public StationTaskIdleTrack loadIdleTrack(Integer taskNo) {
|
if (taskNo == null || taskNo <= 0 || redisUtil == null) {
|
return null;
|
}
|
Object obj = redisUtil.get(RedisKeyType.STATION_TASK_IDLE_TRACK_.key + taskNo);
|
if (obj == null) {
|
return null;
|
}
|
try {
|
return JSON.parseObject(obj.toString(), StationTaskIdleTrack.class);
|
} catch (Exception e) {
|
return null;
|
}
|
}
|
|
public void saveIdleTrack(StationTaskIdleTrack idleTrack) {
|
if (idleTrack == null || idleTrack.getTaskNo() == null || idleTrack.getTaskNo() <= 0 || redisUtil == null) {
|
return;
|
}
|
redisUtil.set(
|
RedisKeyType.STATION_TASK_IDLE_TRACK_.key + idleTrack.getTaskNo(),
|
JSON.toJSONString(idleTrack, SerializerFeature.DisableCircularReferenceDetect),
|
STATION_IDLE_TRACK_EXPIRE_SECONDS
|
);
|
}
|
|
public boolean hasRecentIssuedMoveCommand(Integer taskNo, Integer stationId, long thresholdMs) {
|
if (taskNo == null || taskNo <= 0 || stationId == null || thresholdMs <= 0L || basStationOptService == null) {
|
return false;
|
}
|
Date thresholdTime = new Date(System.currentTimeMillis() - thresholdMs);
|
List<BasStationOpt> optList = basStationOptService.list(new QueryWrapper<BasStationOpt>()
|
.select("id")
|
.eq("task_no", taskNo)
|
.eq("station_id", stationId)
|
.eq("mode", String.valueOf(StationCommandType.MOVE))
|
.eq("send", 1)
|
.ge("send_time", thresholdTime)
|
.orderByDesc("send_time")
|
.last("limit 1"));
|
return optList != null && !optList.isEmpty();
|
}
|
|
public int clearIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack,
|
Integer taskNo,
|
Integer stationId) {
|
if (basStationOptService == null) {
|
return 0;
|
}
|
List<BasStationOpt> optList;
|
try {
|
optList = listIssuedMoveCommandsDuringIdleStay(idleTrack, taskNo);
|
} catch (Exception e) {
|
return 0;
|
}
|
if (optList == null || optList.isEmpty()) {
|
return 0;
|
}
|
|
Date now = new Date();
|
String cleanupMemo = buildIdleRecoverClearedMemo(stationId);
|
int clearedCount = 0;
|
for (BasStationOpt opt : optList) {
|
if (opt == null || opt.getId() == null) {
|
continue;
|
}
|
opt.setSend(0);
|
opt.setUpdateTime(now);
|
opt.setMemo(appendCleanupMemo(opt.getMemo(), cleanupMemo));
|
clearedCount++;
|
}
|
if (clearedCount > 0) {
|
basStationOptService.updateBatchById(optList);
|
}
|
return clearedCount;
|
}
|
|
public boolean tryAcquireLock(String key, int seconds) {
|
if (redisUtil == null || isBlank(key)) {
|
return true;
|
}
|
Object lock = redisUtil.get(key);
|
if (lock != null) {
|
return false;
|
}
|
redisUtil.set(key, "lock", seconds);
|
return true;
|
}
|
|
public boolean tryAcquireOutOrderDispatchLock(Integer wrkNo, Integer stationId, int seconds) {
|
if (wrkNo == null || wrkNo <= 0 || stationId == null) {
|
return true;
|
}
|
return tryAcquireLock(RedisKeyType.STATION_OUT_ORDER_DISPATCH_LIMIT_.key + wrkNo + "_" + stationId, seconds);
|
}
|
|
public void signalSegmentReset(Integer taskNo, long waitMs) {
|
if (redisUtil == null || taskNo == null || taskNo <= 0) {
|
return;
|
}
|
String key = RedisKeyType.DEVICE_STATION_MOVE_RESET.key + taskNo;
|
redisUtil.set(key, "cancel", 3);
|
try {
|
if (waitMs > 0L) {
|
Thread.sleep(waitMs);
|
}
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
} catch (Exception ignore) {
|
}
|
redisUtil.del(key);
|
}
|
|
public StationCommand loadWatchCircleCommand(Integer wrkNo) {
|
if (wrkNo == null || wrkNo <= 0 || redisUtil == null) {
|
return null;
|
}
|
Object circleObj = redisUtil.get(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo);
|
if (circleObj == null) {
|
return null;
|
}
|
try {
|
return JSON.parseObject(circleObj.toString(), StationCommand.class);
|
} catch (Exception ignore) {
|
return null;
|
}
|
}
|
|
public void saveWatchCircleCommand(Integer wrkNo, StationCommand command) {
|
if (wrkNo == null || wrkNo <= 0 || command == null || redisUtil == null) {
|
return;
|
}
|
redisUtil.set(
|
RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo,
|
JSON.toJSONString(command, SerializerFeature.DisableCircularReferenceDetect),
|
60 * 60 * 24
|
);
|
}
|
|
public void clearWatchCircleCommand(Integer wrkNo) {
|
if (wrkNo == null || wrkNo <= 0 || redisUtil == null) {
|
return;
|
}
|
redisUtil.del(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkNo);
|
}
|
|
private List<BasStationOpt> listIssuedMoveCommandsDuringIdleStay(StationTaskIdleTrack idleTrack,
|
Integer taskNo) {
|
if (idleTrack == null || taskNo == null || taskNo <= 0 || idleTrack.getFirstSeenTime() == null || basStationOptService == null) {
|
return Collections.emptyList();
|
}
|
List<BasStationOpt> optList = basStationOptService.list(new QueryWrapper<BasStationOpt>()
|
.select("id", "task_no", "send_time", "target_station_id", "memo", "send")
|
.eq("task_no", taskNo)
|
.eq("mode", String.valueOf(StationCommandType.MOVE))
|
.eq("send", 1)
|
.ge("send_time", new Date(idleTrack.getFirstSeenTime()))
|
.orderByAsc("send_time"));
|
if (optList == null || optList.isEmpty()) {
|
return Collections.emptyList();
|
}
|
return optList;
|
}
|
|
private String buildIdleRecoverClearedMemo(Integer stationId) {
|
if (stationId == null) {
|
return IDLE_RECOVER_CLEARED_MEMO;
|
}
|
return IDLE_RECOVER_CLEARED_MEMO + "(stationId=" + stationId + ")";
|
}
|
|
private String appendCleanupMemo(String memo, String cleanupMemo) {
|
if (Cools.isEmpty(cleanupMemo)) {
|
return memo;
|
}
|
if (Cools.isEmpty(memo)) {
|
return cleanupMemo;
|
}
|
if (memo.contains(cleanupMemo)) {
|
return memo;
|
}
|
return memo + " | " + cleanupMemo;
|
}
|
|
private boolean isBlank(String value) {
|
return value == null || value.trim().isEmpty();
|
}
|
}
|