|
|
|
@ -10,9 +10,12 @@ 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.mes.pcn.serviceimpl.fsm.IShippingDispatchService;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.IStepService;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
|
|
|
|
|
import cn.estsh.i3plus.mes.pcn.websocket.StationWebSocket;
|
|
|
|
|
import cn.estsh.i3plus.platform.common.tool.TimeTool;
|
|
|
|
|
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
|
|
|
|
|
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrderPush;
|
|
|
|
|
import cn.estsh.i3plus.pojo.mes.bean.MesQueueOrderPushCellCfg;
|
|
|
|
@ -57,6 +60,9 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
@Autowired
|
|
|
|
|
private IFsmCommonService fsmCommonService;
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private IShippingDispatchService shippingDispatchService;
|
|
|
|
|
|
|
|
|
|
private static Map<String, String> lockTimeMap = new HashMap<>();
|
|
|
|
|
private static Map<String, ReentrantLock> lockMap = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
|
|
@ -112,10 +118,10 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
getStepParams(reqBean), MesPcnExtConstWords.READ_FAILURE_SLEEP, MesPcnExtConstWords.READ_FAILURE_SLEEP_DEFAULT_TIME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//搜集需要考虑加锁的推送来源代码
|
|
|
|
|
//搜集需要加锁的推送来源代码
|
|
|
|
|
List<String> pushSourceCodeList2NeedLock = queueOrderPushCellCfgList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsNeedLock()))).map(MesQueueOrderPushCellCfg::getPushSourceCode).collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
//当前即将执行的接收队列
|
|
|
|
|
//当前即将执行的推送队列
|
|
|
|
|
List<MesQueueOrderPush> curPushList = null;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
@ -123,18 +129,27 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
for (MesQueueOrderPush queueOrderPush : queueOrderPushList) {
|
|
|
|
|
if (null == queueOrderPush || StringUtils.isEmpty(queueOrderPush.getWorkOrderNo())) continue;
|
|
|
|
|
//当前遍历中的代码不考虑加锁
|
|
|
|
|
if (CollectionUtils.isEmpty(pushSourceCodeList2NeedLock) || !pushSourceCodeList2NeedLock.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;
|
|
|
|
|
productionCustomContextStepService.getSortQueuePushLockContext(reqBean, reqBean.getWorkCenterCode());
|
|
|
|
|
// if (!CollectionUtils.isEmpty(queuePushIdList) && queuePushIdList.contains(queueOrderPush.getId().toString())) continue;
|
|
|
|
|
if (!CollectionUtils.isEmpty(pushSourceCodeList2NeedLock) && pushSourceCodeList2NeedLock.contains(queueOrderPush.getPushSourceCode())) {
|
|
|
|
|
//当前遍历中的代码加锁; 获取不到锁的情况下退出循环
|
|
|
|
|
if (!tryLock(reqBean, queueOrderPush.getPushSourceCode())) break;
|
|
|
|
|
//获取排序线工单队列推送锁数据, 返回的值是工位代码
|
|
|
|
|
String lockedCellCode = productionCustomContextStepService.getSortQueuePushLockContext(reqBean, queueOrderPush.getId().toString());
|
|
|
|
|
//如果当前推送信息的ID已被其他工位锁定, 验证锁定的工位是否在线, 不在线直接清除当前推送信息的ID的LOCK
|
|
|
|
|
if (!StringUtils.isEmpty(lockedCellCode) && !lockedCellCode.equals(reqBean.getWorkCellCode())) {
|
|
|
|
|
if (!CollectionUtils.isEmpty(StationWebSocket.getStationWebSocketList(
|
|
|
|
|
shippingDispatchService.getActorClientInfo(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), lockedCellCode)))) continue;
|
|
|
|
|
else productionCustomContextStepService.removeSortQueuePushLockContext(reqBean, queueOrderPush.getId().toString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queueOrderPush.setIsNeedLock(CommonEnumUtil.TRUE_OR_FALSE.TRUE.getValueStr());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//ADD到当前即将执行的推送队列中
|
|
|
|
|
if (CollectionUtils.isEmpty(curPushList)) curPushList = new ArrayList<>();
|
|
|
|
|
curPushList.add(queueOrderPush);
|
|
|
|
|
|
|
|
|
|
//满足腔数的情况下退出循环
|
|
|
|
|
if (curPushList.size() >= cellEquipContext.getCavity()) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证是否满足腔数
|
|
|
|
@ -171,57 +186,59 @@ public class MesWorkOrderQueueAcceptStepService extends BaseStepService {
|
|
|
|
|
return stepResult;
|
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
|
|
// //验证是否执行解锁
|
|
|
|
|
// List<MesQueueOrderPush> pushList2NeedLock = (CollectionUtils.isEmpty(curPushList) || CollectionUtils.isEmpty(pushSourceCodeList2NeedLock)) ? null :
|
|
|
|
|
// curPushList.stream().filter(o -> (null != o && pushSourceCodeList2NeedLock.contains(o.getPushSourceCode()))).collect(Collectors.toList());
|
|
|
|
|
// //当需要考虑加锁且满足腔数的情况下, 保存排序线工单队列推送锁数据
|
|
|
|
|
// if (!CollectionUtils.isEmpty(pushList2NeedLock) && curPushList.size() >= cellEquipContext.getCavity()) {
|
|
|
|
|
// List<String> idList = pushList2NeedLock.stream().filter(o -> null != o).map(o -> String.valueOf(o.getId())).collect(Collectors.toList());
|
|
|
|
|
// productionCustomContextStepService.dispatchSortQueuePushLockContext(reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), idList);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// //解锁
|
|
|
|
|
// if (!CollectionUtils.isEmpty(pushList2NeedLock)) pushList2NeedLock.forEach(o -> unLock(reqBean.getWorkCenterCode(), o.getPushSourceCode()));
|
|
|
|
|
//当需要加锁且满足腔数的情况下, 保存排序线工单队列推送锁数据【保存LOCK信息:item=id,value=工位】【保存当前工位锁定的信息:item=工位,value=idList】
|
|
|
|
|
List<String> queuePushIdList = CollectionUtils.isEmpty(curPushList) ? null :
|
|
|
|
|
curPushList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsNeedLock()))).map(o -> o.getId().toString()).collect(Collectors.toList());
|
|
|
|
|
if (!CollectionUtils.isEmpty(queuePushIdList) && curPushList.size() >= cellEquipContext.getCavity()) {
|
|
|
|
|
productionCustomContextStepService.dispatchSortQueuePushLockContext(reqBean, queuePushIdList);
|
|
|
|
|
}
|
|
|
|
|
//解锁
|
|
|
|
|
if (!CollectionUtils.isEmpty(queuePushIdList)) queuePushIdList.forEach(o -> unLock(reqBean, o));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//加锁
|
|
|
|
|
private Boolean tryLock(String workCenterCode, String pushSourceCode) {
|
|
|
|
|
private Boolean tryLock(StationRequestBean reqBean, String pushSourceCode) {
|
|
|
|
|
try {
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(workCenterCode).add(pushSourceCode).toString();
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(reqBean.getWorkCenterCode()).add(pushSourceCode).toString();
|
|
|
|
|
ReentrantLock lock = lockMap.computeIfAbsent(key, item -> new ReentrantLock(true));
|
|
|
|
|
//500ms内拿不到锁的情况下监控锁是否已经超时
|
|
|
|
|
if (!lock.tryLock(MesPcnExtConstWords.FIVE_HUNDRED, TimeUnit.MILLISECONDS) && checkTimeOut(key, lock)) return false;
|
|
|
|
|
if (!lock.tryLock(MesPcnExtConstWords.FIVE_HUNDRED, TimeUnit.MILLISECONDS) && checkTimeOut(reqBean, pushSourceCode, key, lock)) return false;
|
|
|
|
|
lockTimeMap.put(key, TimeTool.getNowTime(true));
|
|
|
|
|
return true;
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- tryLock [{}] EXCEPTION: {}",
|
|
|
|
|
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), pushSourceCode, e.toString());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//监控超过10秒的情况下进行自动解锁
|
|
|
|
|
private Boolean checkTimeOut(String key, ReentrantLock lock) {
|
|
|
|
|
private Boolean checkTimeOut(StationRequestBean reqBean, String pushSourceCode, 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();
|
|
|
|
|
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- checkTimeOut [{}] EXCEPTION: {}",
|
|
|
|
|
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), pushSourceCode, e.toString());
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//解锁
|
|
|
|
|
private void unLock(String workCenterCode, String pushSourceCode) {
|
|
|
|
|
private void unLock(StationRequestBean reqBean, String pushSourceCode) {
|
|
|
|
|
try {
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(workCenterCode).add(pushSourceCode).toString();
|
|
|
|
|
String key = new StringJoiner(MesPcnExtConstWords.AND).add(reqBean.getWorkCenterCode()).add(pushSourceCode).toString();
|
|
|
|
|
lockMap.computeIfPresent(key, (k, v) -> {
|
|
|
|
|
if (!v.isHeldByCurrentThread() || !v.isLocked()) return v;
|
|
|
|
|
v.unlock();
|
|
|
|
|
return v;
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.info("工厂{}生产线{}工位{}:FSM STATE DISPATCHER --- DO STEP --- {} EXEC --- unLock [{}] EXCEPTION: {}",
|
|
|
|
|
reqBean.getOrganizeCode(), reqBean.getWorkCenterCode(), reqBean.getWorkCellCode(), StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()), pushSourceCode, e.toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|