|
|
|
@ -9,6 +9,7 @@ import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
|
|
|
|
|
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.actor.shipping.dispatch.IFsmCommonService;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
|
|
|
|
|
import cn.estsh.i3plus.platform.common.tool.TimeTool;
|
|
|
|
|
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrderPush;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrderPushCellCfg;
|
|
|
|
@ -22,10 +23,11 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Description : 工位工单接收工步
|
|
|
|
@ -50,7 +52,8 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
@Autowired
|
|
|
|
|
private IFsmCommonService fsmCommonService;
|
|
|
|
|
|
|
|
|
|
protected static Map<String, ReentrantLock> queueAcceptLockMap = new ConcurrentHashMap<>();
|
|
|
|
|
private static Map<String, String> lockTimeMap = new HashMap<>();
|
|
|
|
|
private static Map<String, ReentrantLock> lockMap = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public StepResult init(StationRequestBean reqBean) {
|
|
|
|
@ -96,8 +99,50 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
MesCellEquipContext cellEquipContext = productionProcessContext.getCurCellEquip();
|
|
|
|
|
|
|
|
|
|
//根据配置查询生产队列工位推送信息
|
|
|
|
|
List<MesQueueOrderPush> queueOrderPushList = queueOrderPushService.getQueueOrderPushList(reqBean.getOrganizeCode(), queueOrderPushCellCfgList, cellEquipContext.getCavity());
|
|
|
|
|
if (CollectionUtils.isEmpty(queueOrderPushList) || queueOrderPushList.size() != cellEquipContext.getCavity()) {
|
|
|
|
|
List<MesQueueOrderPush> queueOrderPushList = queueOrderPushService.getQueueOrderPushList(reqBean.getOrganizeCode(), queueOrderPushCellCfgList);
|
|
|
|
|
if (CollectionUtils.isEmpty(queueOrderPushList) || queueOrderPushList.size() < cellEquipContext.getCavity()) {
|
|
|
|
|
return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().checkRepeat(), stepResult,
|
|
|
|
|
false, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT,
|
|
|
|
|
CollectionUtils.isEmpty(queueOrderPushList) ? "当前未接收到工位工单队列,持续监听中..." : String.format("当前接收到到工位工单队列个数[%s]不满足腔数[%s],持续监听中...", queueOrderPushList.size(), cellEquipContext.getCavity()),
|
|
|
|
|
getStepParams(reqBean), MesPcnExtConstWords.READ_FAILURE_SLEEP, MesPcnExtConstWords.READ_FAILURE_SLEEP_DEFAULT_TIME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//搜集需要考虑加锁的推送来源代码
|
|
|
|
|
List<String> pushSourceCodeList = queueOrderPushCellCfgList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsNeedLock()))).map(MesQueueOrderPushCellCfg::getPushSourceCode).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
//验证是否执行加锁
|
|
|
|
|
List<MesQueueOrderPush> curPushList = null;
|
|
|
|
|
for (MesQueueOrderPush queueOrderPush : queueOrderPushList) {
|
|
|
|
|
if (null == queueOrderPush) continue;
|
|
|
|
|
//当前遍历中的代码不考虑加锁
|
|
|
|
|
if (CollectionUtils.isEmpty(pushSourceCodeList) || !pushSourceCodeList.contains(queueOrderPush.getPushSourceCode())) {
|
|
|
|
|
if (CollectionUtils.isEmpty(curPushList)) curPushList = new ArrayList<>();
|
|
|
|
|
curPushList.add(queueOrderPush);
|
|
|
|
|
//满足腔数的情况下退出循环
|
|
|
|
|
if (curPushList.size() >= cellEquipContext.getCavity()) break;
|
|
|
|
|
} else {
|
|
|
|
|
//当前遍历中的代码考虑加锁; 获取不到锁的情况下退出循环
|
|
|
|
|
if (!tryLock(reqBean.getWorkCenterCode(), queueOrderPush.getPushSourceCode())) break;
|
|
|
|
|
List<String> queuePushIdList = productionCustomContextStepService.getSortQueuePushLockContext(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode());
|
|
|
|
|
if (!CollectionUtils.isEmpty(queuePushIdList) && queuePushIdList.contains(queueOrderPush.getId().toString())) continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证是否执行解锁
|
|
|
|
|
if (!CollectionUtils.isEmpty(curPushList)) {
|
|
|
|
|
for (MesQueueOrderPush queueOrderPush : curPushList) {
|
|
|
|
|
if (null == queueOrderPush) continue;
|
|
|
|
|
if (CollectionUtils.isEmpty(pushSourceCodeList) || !pushSourceCodeList.contains(queueOrderPush.getPushSourceCode())) continue;
|
|
|
|
|
//当需要考虑加锁且满足腔数的情况下, 保存排序线工单队列推送锁数据
|
|
|
|
|
if (curPushList.size() >= cellEquipContext.getCavity()) productionCustomContextStepService.dispatchSortQueuePushLockContext(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), queueOrderPush.getId().toString());
|
|
|
|
|
//解锁
|
|
|
|
|
unLock(reqBean.getWorkCenterCode(), queueOrderPush.getPushSourceCode());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证是否满足腔数
|
|
|
|
|
if (CollectionUtils.isEmpty(curPushList) || curPushList.size() < cellEquipContext.getCavity()) {
|
|
|
|
|
return stepDynamicsCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog().checkRepeat(), stepResult,
|
|
|
|
|
false, MesPcnEnumUtil.STATION_BUSI_TYPE.GUIDE, MesPcnEnumUtil.STATION_DATA_TYPE.TEXT,
|
|
|
|
|
CollectionUtils.isEmpty(queueOrderPushList) ? "当前未接收到工位工单队列,持续监听中..." : String.format("当前接收到到工位工单队列个数[%s]不满足腔数[%s],持续监听中...", queueOrderPushList.size(), cellEquipContext.getCavity()),
|
|
|
|
@ -113,4 +158,42 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//加锁
|
|
|
|
|
private Boolean tryLock(String workCenterCode, String pushSourceCode) {
|
|
|
|
|
try {
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(workCenterCode).add(pushSourceCode).toString();
|
|
|
|
|
ReentrantLock lock = lockMap.computeIfAbsent(key, item -> new ReentrantLock(true));
|
|
|
|
|
//拿不到锁的情况下监控锁是否已经超时
|
|
|
|
|
if (!lock.tryLock(MesPcnExtConstWords.ONE_HUNDRED, TimeUnit.MILLISECONDS) && checkTimeOut(key, lock)) return false;
|
|
|
|
|
lockTimeMap.put(key, TimeTool.getNowTime(true));
|
|
|
|
|
return true;
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//监控超过10秒的情况下进行自动解锁
|
|
|
|
|
private Boolean checkTimeOut(String key, ReentrantLock lock) {
|
|
|
|
|
try {
|
|
|
|
|
String lockTime = lockTimeMap.get(key);
|
|
|
|
|
if ((StringUtils.isEmpty(lockTime) || TimeTool.getSecoundsBetweenTime(1, lockTime, TimeTool.getNowTime(true)) >= MesPcnExtConstWords.TEN) && lock.isLocked()) lock.unlock();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
if (lock.isLocked()) lock.unlock();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//解锁
|
|
|
|
|
private void unLock(String workCenterCode, String pushSourceCode) {
|
|
|
|
|
try {
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(workCenterCode).add(pushSourceCode).toString();
|
|
|
|
|
lockMap.computeIfPresent(key, (k, v) -> {
|
|
|
|
|
if (!v.isHeldByCurrentThread() || !v.isLocked()) return v;
|
|
|
|
|
v.unlock();
|
|
|
|
|
return v;
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|