uat-temp-wj-shenshanorder
王杰 2 months ago
parent 17ec31db78
commit 228aa76db7

@ -103,11 +103,14 @@ public interface IMesProductionCustomContextStepService {
@ApiOperation(value = "删除打包数据")
void removePackageDataContext(StationRequestBean reqBean);
@ApiOperation(value = "获取排序线工单队列推送锁数据")
@ApiOperation(value = "获取排序线工单队列推送锁数据, 返回的值是工位代码")
String getSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);
@ApiOperation(value = "保存排序线工单队列推送锁数据")
Boolean dispatchSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);
@ApiOperation(value = "获取排序线工单队列推送锁数据, 返回的值是工单队列ID集合")
List<String> getSortQueuePushLockContext(StationRequestBean reqBean);
@ApiOperation(value = "保存排序线工单队列推送锁数据【保存LOCK信息:item=id,value=工位】【保存当前工位锁定的信息:item=工位,value=idList】")
Boolean dispatchSortQueuePushLockContext(StationRequestBean reqBean, List<String> queuePushIdList);
@ApiOperation(value = "删除排序线工单队列推送锁数据")
void removeSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId);

@ -12,6 +12,11 @@ import cn.estsh.impp.framework.boot.util.SpringContextsUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.LinkedList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Description :
@ -24,34 +29,38 @@ public class MesProductionDataSaveStepService extends BaseStepService {
@Autowired
public IMesProductionProcessContextStepService productionProcessContextStepService;
@Override
public StepResult execute(StationRequestBean reqBean) {
//是否排序线
Boolean isSort = MesExtEnumUtil.WORK_CENTER_TYPE.SORT.getValue() == productionProcessContextStepService.getCenterType(reqBean) ? true : false;
//【非排序线】保存结果结果工步集合
//保存开模记录工步>>保存零件条码信息工步>>加工异常处理工步>>生成加工记录工步>>保存装配记录工步>>保存工单信息工步
private static final LinkedList<String> noSortStepList = new LinkedList<>(Stream.of(
"mesMouldRecordGenerateStepService", "mesProductSnSaveStepService", "mesProductResultErrorHandleStepService",
"mesProductionRecordGenerateStepService", "mesAssemblySaveStepService", "mesWorkOrderSaveStepService").collect(Collectors.toList()));
//保存开模记录工步
((IStepService) SpringContextsUtil.getBean("mesMouldRecordGenerateStepService")).executeInState(reqBean);
//【排序线】保存结果结果工步集合
//保存开模记录工步>>保存零件条码信息工步>>保存工位队列信息工步>>加工异常处理工步>>生成加工记录工步>>保存工单信息工步
private static final LinkedList<String> sortStepList = new LinkedList<>(Stream.of(
"mesMouldRecordGenerateStepService", "mesProductSnSaveStepService", "mesWorkOrderQueueSaveStepService",
"mesProductResultErrorHandleStepService", "mesProductionRecordGenerateStepService", "mesWorkOrderSaveStepService").collect(Collectors.toList()));
//保存零件条码信息工步
((IStepService) SpringContextsUtil.getBean("mesProductSnSaveStepService")).executeInState(reqBean);
//保存工位队列信息工步 【排序】
if (isSort) ((IStepService) SpringContextsUtil.getBean("mesWorkOrderQueueSaveStepService")).executeInState(reqBean);
@Override
public StepResult execute(StationRequestBean reqBean) {
//加工异常处理工步
((IStepService) SpringContextsUtil.getBean("mesProductResultErrorHandleStepService")).executeInState(reqBean);
StationResultBean resultBean = new StationResultBean();
//生成加工记录工步
((IStepService) SpringContextsUtil.getBean("mesProductionRecordGenerateStepService")).executeInState(reqBean);
StepResult stepResult = StepResult.getSuccessComplete();
//保存装配记录工步 【非排序】
if (!isSort)((IStepService) SpringContextsUtil.getBean("mesAssemblySaveStepService")).executeInState(reqBean);
//根据生产线类型赋值工步集合
Boolean isSort = MesExtEnumUtil.WORK_CENTER_TYPE.SORT.getValue() == productionProcessContextStepService.getCenterType(reqBean) ? true : false;
LinkedList<String> stepList = !isSort ? noSortStepList : sortStepList;
//保存工单信息工步
((IStepService) SpringContextsUtil.getBean("mesWorkOrderSaveStepService")).executeInState(reqBean);
for (String stepService : stepList) {
if (StringUtils.isEmpty(stepResult)) continue;
StepResult innerStepResult = ((IStepService) SpringContextsUtil.getBean(stepService)).executeInState(reqBean);
if (!StringUtils.isEmpty(innerStepResult.getNextTriggerEvent())) stepResult.nextTriggerEvent(innerStepResult.getNextTriggerEvent());
if (!StringUtils.isEmpty(innerStepResult.getStepAfterState())) stepResult.stepAfterState(innerStepResult.getStepAfterState());
if (!innerStepResult.isCompleted()) return stepNonCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工结果失败!");
}
return stepSuccessCompleteAndSendMsgReturn(reqBean, new StationResultBean().writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), "保存加工结果成功!");
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存加工结果成功!");
}

@ -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());
}
}

@ -1,5 +1,6 @@
package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.step;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionCustomContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionDispatchContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesProductionProcessContextStepService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesQueueOrderPushService;
@ -8,6 +9,7 @@ import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionProcessContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.context.MesProductionPsInContext;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.serviceimpl.fsm.BaseStepService;
import cn.estsh.i3plus.mes.pcn.util.StringUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.MesPcnEnumUtil;
@ -24,6 +26,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Optional;
@ -44,6 +47,9 @@ public class MesWorkOrderQueueSavePushStepService extends BaseStepService {
private IMesProductionDispatchContextStepService productionDispatchContextStepService;
@Autowired
private IMesProductionCustomContextStepService productionCustomContextStepService;
@Autowired
private IMesQueueOrderPushService queueOrderPushService;
@Autowired
@ -79,6 +85,10 @@ public class MesWorkOrderQueueSavePushStepService extends BaseStepService {
//写入队列信息,默认状态为已完成
productionPsInContextList.stream().filter(o -> null != o).forEach(o -> insertQueueOrder(reqBean, o, productionPartContextList));
//验证是否存在LOCK数据, 存在的情况下赋值 stepAfterState, 当前工步集执行结束后会执行当前工步重写的executeStepAfterState方法
Optional<MesQueueOrderPush> optional = CollectionUtils.isEmpty(queueOrderPushList) ? null : queueOrderPushList.stream().filter(o -> (null != o && !StringUtils.isEmpty(o.getIsNeedLock()))).findFirst();
if (null != optional && optional.isPresent()) stepResult.stepAfterState(StringUtil.toLowerCaseFirst(this.getClass().getSimpleName()));
return stepSuccessCompleteAndSendMsgReturn(reqBean, resultBean.writeDbLog(MesPcnEnumUtil.WORK_CELL_SCAN_MONITOR_LOG_TYPE.PROCESS.getValue()), stepResult, "保存工位队列成功!");
}
@ -104,4 +114,15 @@ public class MesWorkOrderQueueSavePushStepService extends BaseStepService {
queueOrderRepository.insert(queueOrder);
}
//当前工步集完成之后执行当前方法
@Override
public void executeStepAfterState(StationRequestBean reqBean, StepResult stepResult) {
if (!stepResult.isCompleted()) return;
//获取排序线工单队列推送锁数据, 返回的值是工单队列ID集合
List<String> queuePushIdList = productionCustomContextStepService.getSortQueuePushLockContext(reqBean);
if (CollectionUtils.isEmpty(queuePushIdList)) return;
//删除排序线工单队列推送锁数据
queuePushIdList.stream().filter(o -> !StringUtils.isEmpty(o)).forEach(o -> productionCustomContextStepService.removeSortQueuePushLockContext(reqBean, o));
}
}

@ -217,7 +217,6 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
@Override
public String getRepeatAssemblySn(String organizeCode, String workCenterCode, String workCellCode, String repeatKey) {
String repeatAssemblySnJson = getFsmBusiData(organizeCode, getRepeatAssemblySnContextKey(organizeCode, workCenterCode, workCellCode), repeatKey);
//MesProductionAssemblyContext productionAssemblyContext = !StringUtils.isEmpty(repeatAssemblySnJson) ? JSONObject.parseObject(repeatAssemblySnJson, MesProductionAssemblyContext.class) : null;
return repeatAssemblySnJson;
}
@ -299,22 +298,33 @@ public class MesProductionCustomContextStepService extends BaseStepService imple
//排序线工单队列推送锁数据KEY 【PS:生产线级别】
private String getSortQueuePushLockContextKey(StationRequestBean reqBean) { return new StringJoiner(MesPcnExtConstWords.COLON).add(reqBean.getOrganizeCode()).add(reqBean.getWorkCenterCode()).add(MesPcnExtConstWords.QUEUE_PUSH_LOCK_CONTEXT).toString(); }
//获取排序线工单队列推送锁数据
//获取排序线工单队列推送锁数据, 返回的值是工位代码
@Override
public String getSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId) {
if (StringUtils.isEmpty(queuePushId)) return null;
return getFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
}
//保存排序线工单队列推送锁数据
//获取排序线工单队列推送锁数据, 返回的值是工单队列ID集合
@Override
public Boolean dispatchSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId) {
return dispatchFsmBusiList(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
public List<String> getSortQueuePushLockContext(StationRequestBean reqBean) {
String queuePushIdListJson = getFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), reqBean.getWorkCellCode());
return StringUtils.isEmpty(queuePushIdListJson) ? null : JSONObject.parseArray(queuePushIdListJson, String.class);
}
//保存排序线工单队列推送锁数据【保存LOCK信息:item=id,value=工位】【保存当前工位锁定的信息:item=工位,value=idList】
@Override
public Boolean dispatchSortQueuePushLockContext(StationRequestBean reqBean, List<String> queuePushIdList) {
if (CollectionUtils.isEmpty(queuePushIdList)) return false;
queuePushIdList.forEach(o -> dispatchFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), o, reqBean.getWorkCellCode()));
return dispatchFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), reqBean.getWorkCellCode(), JSONObject.toJSONString(queuePushIdList));
}
//删除排序线工单队列推送锁数据
@Override
public void removeSortQueuePushLockContext(StationRequestBean reqBean, String queuePushId) {
removeFsmBusiList(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
if (!StringUtils.isEmpty(queuePushId)) return;
removeFsmBusiData(reqBean.getOrganizeCode(), getSortQueuePushLockContextKey(reqBean), queuePushId);
}
}

Loading…
Cancel
Save