package com.zy.core.plugin.store; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.Cools; import com.zy.asrs.domain.param.CreateInTaskParam; import com.zy.asrs.entity.BasDevp; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.service.BasDevpService; import com.zy.asrs.service.WrkMastService; import com.zy.common.model.StartupDto; import com.zy.common.service.CommonService; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.RedisKeyType; import com.zy.core.enums.SlaveType; import com.zy.core.model.StationObjModel; import com.zy.core.model.protocol.StationProtocol; import com.zy.core.thread.StationThread; import com.zy.core.utils.StationOperateProcessUtils; import com.zy.core.utils.WmsOperateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @Service public class StoreInTaskGenerationService { private static final int APPLY_IN_TASK_TIMEOUT_SECONDS = 5; @Autowired private BasDevpService basDevpService; @Autowired private WrkMastService wrkMastService; @Autowired private StationOperateProcessUtils stationOperateProcessUtils; @Autowired private RedisUtil redisUtil; @Autowired private WmsOperateUtils wmsOperateUtils; @Autowired private CommonService commonService; private final AtomicInteger inFlightGenerateCount = new AtomicInteger(0); public void generate(StoreInTaskPolicy policy) { try { if (!policy.isEnabled()) { return; } HashMap systemConfigMap = getSystemConfigMap(); if (systemConfigMap == null) { return; } if (!hasAvailableStationTaskCapacity(systemConfigMap)) { return; } List basDevps = basDevpService.list(new QueryWrapper<>()); for (BasDevp basDevp : basDevps) { List barcodeStations = policy.getBarcodeStations(basDevp); for (StationObjModel stationObjModel : barcodeStations) { generate(policy, basDevp, stationObjModel, systemConfigMap); } } } catch (Exception e) { News.error("生成入库任务异常,policy={}", policy.getPolicyName(), e); } } public void generate(StoreInTaskPolicy policy, BasDevp basDevp, StationObjModel stationObjModel) { try { if (!policy.isEnabled()) { return; } HashMap systemConfigMap = getSystemConfigMap(); if (systemConfigMap == null) { return; } if (!hasAvailableStationTaskCapacity(systemConfigMap)) { return; } generate(policy, basDevp, stationObjModel, systemConfigMap); } catch (Exception e) { Integer stationId = stationObjModel == null ? null : stationObjModel.getStationId(); News.error("生成入库任务异常,policy={},stationId={}", policy.getPolicyName(), stationId, e); } } private void generate(StoreInTaskPolicy policy, BasDevp basDevp, StationObjModel stationObjModel, HashMap systemConfigMap) { if (basDevp == null || stationObjModel == null || stationObjModel.getStationId() == null) { return; } StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); if (stationThread == null) { return; } Integer stationId = stationObjModel.getStationId(); Map stationMap = stationThread.getStatusMap(); if (!stationMap.containsKey(stationId)) { return; } StationProtocol stationProtocol = stationMap.get(stationId); if (stationProtocol == null) { return; } StoreInTaskContext context = new StoreInTaskContext(basDevp, stationThread, stationObjModel, stationProtocol); if (!policy.matchCandidate(context)) { return; } if (!policy.beforeApply(context)) { return; } List wrkMasts = wrkMastService.list(new QueryWrapper() .eq("barcode", stationProtocol.getBarcode())); if (!wrkMasts.isEmpty()) { return; } String generateLockKey = policy.getGenerateLockKey(context); Object lock = redisUtil.get(generateLockKey); if (lock != null) { return; } if (!tryReserveGenerateCapacity(systemConfigMap)) { return; } try { policy.onRequestPermitGranted(context); InTaskApplyRequest request = policy.buildApplyRequest(context); policy.setSystemWarning(context, "请求WMS中"); News.info("发起同步WMS入库请求,barcode={},stationId={},timeout={}s", request.getBarcode(), request.getSourceStaNo(), APPLY_IN_TASK_TIMEOUT_SECONDS); InTaskApplyResult result = applySyncInTask(request); handleApplyResult(policy, context, request, result); } finally { releaseGenerateCapacity(); } } private void handleApplyResult(StoreInTaskPolicy policy, StoreInTaskContext context, InTaskApplyRequest request, InTaskApplyResult result) { if (result.isSuccess()) { handleApplySuccess(policy, context, request, result); return; } if (result.isRetryableFailure()) { News.error("WMS入库请求失败,barcode={},stationId={},response={}", request.getBarcode(), request.getSourceStaNo(), policy.buildFailureMessage(result)); redisUtil.set(policy.getGenerateLockKey(context), "lock", policy.getRetryLockSeconds(context)); policy.onApplyFailed(context, result); return; } policy.onApplyFailed(context, result); } private void handleApplySuccess(StoreInTaskPolicy policy, StoreInTaskContext context, InTaskApplyRequest request, InTaskApplyResult result) { try { JSONObject jsonObject = JSON.parseObject(result.getResponse()); if (jsonObject == null || !Integer.valueOf(200).equals(jsonObject.getInteger("code"))) { InTaskApplyResult failResult = new InTaskApplyResult(); failResult.setStatus(InTaskApplyStatus.RETRYABLE_FAIL); failResult.setResponse(result.getResponse()); failResult.setMessage("WMS返回非200"); handleApplyResult(policy, context, request, failResult); return; } StartupDto dto = jsonObject.getObject("data", StartupDto.class); if (dto == null) { InTaskApplyResult failResult = new InTaskApplyResult(); failResult.setStatus(InTaskApplyStatus.RETRYABLE_FAIL); failResult.setResponse(result.getResponse()); failResult.setMessage("WMS返回data为空"); handleApplyResult(policy, context, request, failResult); return; } CreateInTaskParam taskParam = policy.buildCreateInTaskParam(context, dto); WrkMast wrkMast = commonService.createInTask(taskParam); policy.afterTaskCreated(context, wrkMast); policy.clearSystemWarning(context); } catch (Exception e) { News.error("处理WMS入库成功响应失败,barcode={},stationId={}", request.getBarcode(), request.getSourceStaNo(), e); } } private InTaskApplyResult applySyncInTask(InTaskApplyRequest request) { InTaskApplyResult result = new InTaskApplyResult(); result.setBizKey(request.getBizKey()); String response = wmsOperateUtils.applyInTask(request); result.setResponse(response); if (Cools.isEmpty(response)) { result.setStatus(InTaskApplyStatus.RETRYABLE_FAIL); result.setMessage("FAILED"); return result; } try { JSONObject jsonObject = JSON.parseObject(response); if (jsonObject != null && Integer.valueOf(200).equals(jsonObject.getInteger("code"))) { result.setStatus(InTaskApplyStatus.SUCCESS); return result; } } catch (Exception ignored) { } result.setStatus(InTaskApplyStatus.RETRYABLE_FAIL); result.setMessage(response); return result; } private HashMap getSystemConfigMap() { Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key); if (systemConfigMapObj == null) { return null; } return (HashMap) systemConfigMapObj; } private boolean hasAvailableStationTaskCapacity(HashMap systemConfigMap) { int conveyorStationTaskLimit = getConveyorStationTaskLimit(systemConfigMap); int currentStationTaskCount = stationOperateProcessUtils.getCurrentStationTaskCount(); if (currentStationTaskCount > conveyorStationTaskLimit) { News.error("输送站点任务已达到上限,上限值:{},站点任务数:{}", conveyorStationTaskLimit, currentStationTaskCount); return false; } return true; } private boolean tryReserveGenerateCapacity(HashMap systemConfigMap) { int conveyorStationTaskLimit = getConveyorStationTaskLimit(systemConfigMap); while (true) { int reservedCount = inFlightGenerateCount.get(); int currentStationTaskCount = stationOperateProcessUtils.getCurrentStationTaskCount(); if (currentStationTaskCount + reservedCount >= conveyorStationTaskLimit) { News.error("输送站点任务已达到上限,上限值:{},站点任务数:{},生成中任务数:{}", conveyorStationTaskLimit, currentStationTaskCount, reservedCount); return false; } if (inFlightGenerateCount.compareAndSet(reservedCount, reservedCount + 1)) { return true; } } } private void releaseGenerateCapacity() { inFlightGenerateCount.updateAndGet(current -> current > 0 ? current - 1 : 0); } private int getConveyorStationTaskLimit(HashMap systemConfigMap) { int conveyorStationTaskLimit = 30; String conveyorStationTaskLimitStr = systemConfigMap.get("conveyorStationTaskLimit"); if (conveyorStationTaskLimitStr != null) { conveyorStationTaskLimit = Integer.parseInt(conveyorStationTaskLimitStr); } return conveyorStationTaskLimit; } }