package com.vincent.rsf.server.manager.schedules; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.vincent.rsf.server.manager.constant.CloudWmsInoutReportMode; import com.vincent.rsf.server.manager.entity.CloudWmsNotifyLog; import com.vincent.rsf.server.manager.service.CloudWmsNotifyLogService; import com.vincent.rsf.server.manager.service.impl.CloudWmsOrderTaskRunningHelper; import com.vincent.rsf.server.system.constant.GlobalConfigCode; import com.vincent.rsf.server.system.entity.Config; import com.vincent.rsf.server.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * wait_order:按空闲/整单无执行中任务 + 防抖,将暂缓发送的入出库待办放行(数据在 man_cloud_wms_notify_log) */ @Slf4j @Component public class CloudWmsInoutAggSchedule { private static final int DEFAULT_IDLE_SEC = 180; private static final int DEFAULT_DEBOUNCE_SEC = 8; @Autowired private CloudWmsNotifyLogService cloudWmsNotifyLogService; @Autowired private CloudWmsOrderTaskRunningHelper cloudWmsOrderTaskRunningHelper; @Autowired private ConfigService configService; @Scheduled(cron = "0/15 * * * * ?") public void releaseHeldInOutNotifies() { String mode = resolveMode(); if (!CloudWmsInoutReportMode.WAIT_ORDER.equals(mode)) { return; } int idleSec = resolveInt(GlobalConfigCode.CLOUD_WMS_INOUT_AGG_IDLE_SECONDS, DEFAULT_IDLE_SEC); int debounceSec = resolveInt(GlobalConfigCode.CLOUD_WMS_INOUT_AGG_COMPLETE_DEBOUNCE_SECONDS, DEFAULT_DEBOUNCE_SEC); long nowMs = System.currentTimeMillis(); String rt = cloudWmsNotifyLogService.getReportTypeInOutResult(); int pending = cloudWmsNotifyLogService.getNotifyStatusPending(); int fail = cloudWmsNotifyLogService.getNotifyStatusFail(); List heldRows = cloudWmsNotifyLogService.list(new LambdaQueryWrapper() .eq(CloudWmsNotifyLog::getReportType, rt) .eq(CloudWmsNotifyLog::getSendHold, 1) .in(CloudWmsNotifyLog::getNotifyStatus, pending, fail) .isNotNull(CloudWmsNotifyLog::getSourceOrderNo) .apply("(max_retry_count IS NULL OR max_retry_count = -1 OR retry_count < max_retry_count)")); if (heldRows.isEmpty()) { return; } Map> groups = new LinkedHashMap<>(); for (CloudWmsNotifyLog row : heldRows) { if (row == null) { continue; } String key = row.getSourceOrderNo() + "\t" + StringUtils.defaultString(String.valueOf(row.getInboundFlag())) + "\t" + StringUtils.defaultString(row.getWareHouseCode()); groups.computeIfAbsent(key, k -> new ArrayList<>()).add(row); } Date now = new Date(); for (List group : groups.values()) { if (group.isEmpty()) { continue; } CloudWmsNotifyLog first = group.get(0); long maxUt = 0L; for (CloudWmsNotifyLog r : group) { Date u = r.getUpdateTime() != null ? r.getUpdateTime() : r.getCreateTime(); if (u != null) { maxUt = Math.max(maxUt, u.getTime()); } } long ageSec = maxUt <= 0 ? 0 : Math.max(0L, (nowMs - maxUt) / 1000L); boolean running = cloudWmsOrderTaskRunningHelper.hasRunningTasksForPlatOrder(first.getSourceOrderNo()); boolean idleFlush = ageSec >= idleSec; boolean completeFlush = !running && ageSec >= debounceSec; if (!idleFlush && !completeFlush) { continue; } List ids = new ArrayList<>(group.size()); for (CloudWmsNotifyLog r : group) { if (r.getId() != null) { ids.add(r.getId()); } } if (ids.isEmpty()) { continue; } try { LambdaUpdateWrapper u = new LambdaUpdateWrapper<>(); u.in(CloudWmsNotifyLog::getId, ids) .set(CloudWmsNotifyLog::getSendHold, 0) .set(CloudWmsNotifyLog::getUpdateTime, now); cloudWmsNotifyLogService.update(u); } catch (Exception e) { log.warn("云仓 wait_order 放行待办异常:{}", e.getMessage()); } } } private String resolveMode() { try { Config c = configService.getCachedOrLoad(GlobalConfigCode.CLOUD_WMS_INOUT_REPORT_MODE); if (c != null && StringUtils.isNotBlank(c.getVal())) { return c.getVal().trim().toLowerCase(); } } catch (Exception ignored) { } return CloudWmsInoutReportMode.IMMEDIATE; } private int resolveInt(String flag, int defaultVal) { try { Config c = configService.getCachedOrLoad(flag); if (c != null && StringUtils.isNotBlank(c.getVal())) { int v = Integer.parseInt(c.getVal().trim()); return v >= 0 ? v : defaultVal; } } catch (Exception ignored) { } return defaultVal; } }