From e643e4c346976a7a7543364b324d5c5cee982aad Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期四, 26 二月 2026 16:07:01 +0800
Subject: [PATCH] #
---
/dev/null | 161 --------------------------
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java | 165 ++++++++++++++++++++++++---
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/GuaranteeScheduler.java | 1
3 files changed, 144 insertions(+), 183 deletions(-)
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/GuaranteeScheduler.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/GuaranteeScheduler.java
index c2e7601..509a8b6 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/GuaranteeScheduler.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/GuaranteeScheduler.java
@@ -49,7 +49,6 @@
return;
}
List<Guarantee> plans = guaranteeService.list(new LambdaQueryWrapper<Guarantee>()
- .eq(Guarantee::getDeleted, 0)
.eq(Guarantee::getStatus, StatusType.ENABLE.val));
syncCache(plans);
LocalDateTime now = LocalDateTime.now();
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
index 5c5abec..0a38972 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/GuaranteeRuntimeService.java
@@ -1,32 +1,155 @@
package com.zy.acs.manager.core.service;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zy.acs.common.enums.AgvStatusType;
+import com.zy.acs.manager.manager.entity.Agv;
+import com.zy.acs.manager.manager.entity.AgvDetail;
import com.zy.acs.manager.manager.entity.Guarantee;
+import com.zy.acs.manager.manager.entity.Task;
+import com.zy.acs.manager.manager.enums.StatusType;
+import com.zy.acs.manager.manager.enums.TaskStsType;
+import com.zy.acs.manager.manager.enums.TaskTypeType;
+import com.zy.acs.manager.manager.service.AgvDetailService;
+import com.zy.acs.manager.manager.service.AgvService;
+import com.zy.acs.manager.manager.service.TaskService;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
-/**
- * Runtime guarantee orchestration entry.
- */
-public interface GuaranteeRuntimeService {
+@Slf4j
+@Service
+public class GuaranteeRuntimeService {
- /**
- * Lead time entrance: make sure enough vehicles can reach the target window.
- */
- void prepare(Guarantee plan, LocalDateTime targetTime);
+ private final AgvService agvService;
+ private final AgvDetailService agvDetailService;
+ private final TaskService taskService;
+ private final MainLockWrapService mainLockWrapService;
- /**
- * Lock stage: restrict non-essential dispatching for reserve vehicles.
- */
- void lock(Guarantee plan, LocalDateTime targetTime);
+ public GuaranteeRuntimeService(AgvService agvService,
+ AgvDetailService agvDetailService,
+ TaskService taskService,
+ MainLockWrapService mainLockWrapService) {
+ this.agvService = agvService;
+ this.agvDetailService = agvDetailService;
+ this.taskService = taskService;
+ this.mainLockWrapService = mainLockWrapService;
+ }
- /**
- * Executed repeatedly during the guarantee window to keep SLA.
- */
- void checkWindow(Guarantee plan, LocalDateTime targetTime);
+ public void prepare(Guarantee plan, LocalDateTime targetTime) {
+ CapacitySnapshot snapshot = evaluate(plan);
+ if (snapshot.availableCount >= plan.getRequiredCount()) {
+ log.debug("Guarantee[{}] already has {} available vehicles for {}",
+ plan.getName(), snapshot.availableCount, targetTime);
+ return;
+ }
+ int shortage = plan.getRequiredCount() - snapshot.availableCount;
+ log.info("Guarantee[{}] shortage {} vehicles for {} (minSoc={}%), scheduling charge.",
+ plan.getName(), shortage, targetTime, plan.getMinSoc());
+ dispatchChargeTasks(snapshot, shortage);
+ }
- /**
- * Called once after the window ends to release state/records.
- */
- void finish(Guarantee plan, LocalDateTime targetTime);
+ public void lock(Guarantee plan, LocalDateTime targetTime) {
+ log.info("Guarantee[{}] entering lock stage for {}", plan.getName(), targetTime);
+ // TODO persist lock state / inform dispatcher once integration is ready
+ }
+
+ public void checkWindow(Guarantee plan, LocalDateTime targetTime) {
+ CapacitySnapshot snapshot = evaluate(plan);
+ if (snapshot.availableCount < plan.getRequiredCount()) {
+ int shortage = plan.getRequiredCount() - snapshot.availableCount;
+ log.warn("Guarantee[{}] window shortage {} vehicles for {}. Trigger quick recharge.",
+ plan.getName(), shortage, targetTime);
+ dispatchChargeTasks(snapshot, shortage);
+ }
+ }
+
+ public void finish(Guarantee plan, LocalDateTime targetTime) {
+ log.info("Guarantee[{}] finished window for {}", plan.getName(), targetTime);
+ // TODO release any lock/flag once detail implementation is defined
+ }
+
+ private CapacitySnapshot evaluate(Guarantee plan) {
+ int minSoc = Optional.ofNullable(plan.getMinSoc()).orElse(50);
+ List<Agv> scopedAgvs = findScopedAgvs(plan);
+ int available = 0;
+ List<ChargeCandidate> candidates = new ArrayList<>();
+ for (Agv agv : scopedAgvs) {
+ AgvDetail detail = agvDetailService.selectByAgvId(agv.getId());
+ if (detail == null || detail.getSoc() == null) {
+ continue;
+ }
+ if (detail.getSoc() >= minSoc && isAvailable(agv, detail)) {
+ available++;
+ } else {
+ candidates.add(new ChargeCandidate(agv, detail));
+ }
+ }
+ candidates.sort(Comparator.comparingInt(o -> Optional.ofNullable(o.detail.getSoc()).orElse(0)));
+ return new CapacitySnapshot(available, candidates);
+ }
+
+ private boolean isAvailable(Agv agv, AgvDetail detail) {
+ if (!Objects.equals(agv.getStatus(), StatusType.ENABLE.val)) {
+ return false;
+ }
+ if (detail.getAgvStatus() != null && detail.getAgvStatus().equals(AgvStatusType.CHARGE)) {
+ return false;
+ }
+ boolean busy = taskService.count(new LambdaQueryWrapper<Task>()
+ .eq(Task::getAgvId, agv.getId())
+ .in(Task::getTaskSts,
+ TaskStsType.WAITING.val(),
+ TaskStsType.ASSIGN.val(),
+ TaskStsType.PROGRESS.val())) > 0;
+ return !busy;
+ }
+
+ private void dispatchChargeTasks(CapacitySnapshot snapshot, int shortage) {
+ if (shortage <= 0) {
+ return;
+ }
+ int scheduled = 0;
+ for (ChargeCandidate candidate : snapshot.candidates) {
+ if (scheduled >= shortage) {
+ break;
+ }
+ log.info("Scheduling AGV [{}] for charging to support guarantee", candidate.agv.getName());
+ mainLockWrapService.buildMinorTask(candidate.agv.getId(), TaskTypeType.TO_CHARGE, null, null);
+ scheduled++;
+ }
+ }
+
+ private List<Agv> findScopedAgvs(Guarantee plan) {
+ LambdaQueryWrapper<Agv> wrapper = new LambdaQueryWrapper<Agv>()
+ .eq(Agv::getStatus, StatusType.ENABLE.val);
+ if ("MODEL".equalsIgnoreCase(plan.getScopeType()) && plan.getScopeValue() != null) {
+ try {
+ wrapper.eq(Agv::getAgvModel, Long.valueOf(plan.getScopeValue()));
+ } catch (NumberFormatException ignore) {
+ log.warn("Guarantee[{}] invalid scopeValue {}", plan.getName(), plan.getScopeValue());
+ }
+ }
+ return agvService.list(wrapper);
+ }
+
+ @Data
+ private static class CapacitySnapshot {
+ private final int availableCount;
+ private final List<ChargeCandidate> candidates;
+ }
+
+ @Data
+ @AllArgsConstructor
+ private static class ChargeCandidate {
+ private Agv agv;
+ private AgvDetail detail;
+ }
}
-
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/impl/GuaranteeRuntimeServiceImpl.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/impl/GuaranteeRuntimeServiceImpl.java
deleted file mode 100644
index 04163fa..0000000
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/impl/GuaranteeRuntimeServiceImpl.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.zy.acs.manager.core.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.zy.acs.common.enums.AgvStatusType;
-import com.zy.acs.manager.core.service.GuaranteeRuntimeService;
-import com.zy.acs.manager.core.service.MainLockWrapService;
-import com.zy.acs.manager.manager.entity.Agv;
-import com.zy.acs.manager.manager.entity.AgvDetail;
-import com.zy.acs.manager.manager.entity.Guarantee;
-import com.zy.acs.manager.manager.entity.Task;
-import com.zy.acs.manager.manager.enums.StatusType;
-import com.zy.acs.manager.manager.enums.TaskStsType;
-import com.zy.acs.manager.manager.enums.TaskTypeType;
-import com.zy.acs.manager.manager.service.AgvDetailService;
-import com.zy.acs.manager.manager.service.AgvService;
-import com.zy.acs.manager.manager.service.TaskService;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-@Slf4j
-@Service
-public class GuaranteeRuntimeServiceImpl implements GuaranteeRuntimeService {
-
- private final AgvService agvService;
- private final AgvDetailService agvDetailService;
- private final TaskService taskService;
- private final MainLockWrapService mainLockWrapService;
-
- public GuaranteeRuntimeServiceImpl(AgvService agvService,
- AgvDetailService agvDetailService,
- TaskService taskService,
- MainLockWrapService mainLockWrapService) {
- this.agvService = agvService;
- this.agvDetailService = agvDetailService;
- this.taskService = taskService;
- this.mainLockWrapService = mainLockWrapService;
- }
-
- @Override
- public void prepare(Guarantee plan, LocalDateTime targetTime) {
- CapacitySnapshot snapshot = evaluate(plan);
- if (snapshot.availableCount >= plan.getRequiredCount()) {
- log.debug("Guarantee[{}] already has {} available vehicles for {}",
- plan.getName(), snapshot.availableCount, targetTime);
- return;
- }
- int shortage = plan.getRequiredCount() - snapshot.availableCount;
- log.info("Guarantee[{}] shortage {} vehicles for {} (minSoc={}%), scheduling charge.",
- plan.getName(), shortage, targetTime, plan.getMinSoc());
- dispatchChargeTasks(snapshot, shortage);
- }
-
- @Override
- public void lock(Guarantee plan, LocalDateTime targetTime) {
- log.info("Guarantee[{}] entering lock stage for {}", plan.getName(), targetTime);
- // TODO persist lock state / inform dispatcher once integration is ready
- }
-
- @Override
- public void checkWindow(Guarantee plan, LocalDateTime targetTime) {
- CapacitySnapshot snapshot = evaluate(plan);
- if (snapshot.availableCount < plan.getRequiredCount()) {
- int shortage = plan.getRequiredCount() - snapshot.availableCount;
- log.warn("Guarantee[{}] window shortage {} vehicles for {}. Trigger quick recharge.",
- plan.getName(), shortage, targetTime);
- dispatchChargeTasks(snapshot, shortage);
- }
- }
-
- @Override
- public void finish(Guarantee plan, LocalDateTime targetTime) {
- log.info("Guarantee[{}] finished window for {}", plan.getName(), targetTime);
- // TODO release any lock/flag once detail implementation is defined
- }
-
- private CapacitySnapshot evaluate(Guarantee plan) {
- int minSoc = Optional.ofNullable(plan.getMinSoc()).orElse(50);
- List<Agv> scopedAgvs = findScopedAgvs(plan);
- int available = 0;
- List<ChargeCandidate> candidates = new ArrayList<>();
- for (Agv agv : scopedAgvs) {
- AgvDetail detail = agvDetailService.selectByAgvId(agv.getId());
- if (detail == null || detail.getSoc() == null) {
- continue;
- }
- if (detail.getSoc() >= minSoc && isAvailable(agv, detail)) {
- available++;
- } else {
- candidates.add(new ChargeCandidate(agv, detail));
- }
- }
- candidates.sort(Comparator.comparingInt(o -> Optional.ofNullable(o.detail.getSoc()).orElse(0)));
- return new CapacitySnapshot(available, candidates);
- }
-
- private boolean isAvailable(Agv agv, AgvDetail detail) {
- if (!Objects.equals(agv.getStatus(), StatusType.ENABLE.val)) {
- return false;
- }
- if (detail.getAgvStatus() != null && detail.getAgvStatus().equals(AgvStatusType.CHARGE)) {
- return false;
- }
- boolean busy = taskService.count(new LambdaQueryWrapper<Task>()
- .eq(Task::getAgvId, agv.getId())
- .in(Task::getTaskSts,
- TaskStsType.WAITING.val(),
- TaskStsType.ASSIGN.val(),
- TaskStsType.PROGRESS.val())) > 0;
- return !busy;
- }
-
- private void dispatchChargeTasks(CapacitySnapshot snapshot, int shortage) {
- if (shortage <= 0) {
- return;
- }
- int scheduled = 0;
- for (ChargeCandidate candidate : snapshot.candidates) {
- if (scheduled >= shortage) {
- break;
- }
- log.info("Scheduling AGV [{}] for charging to support guarantee", candidate.agv.getName());
- mainLockWrapService.buildMinorTask(candidate.agv.getId(), TaskTypeType.TO_CHARGE, null, null);
- scheduled++;
- }
- }
-
- private List<Agv> findScopedAgvs(Guarantee plan) {
- LambdaQueryWrapper<Agv> wrapper = new LambdaQueryWrapper<Agv>()
- .eq(Agv::getStatus, StatusType.ENABLE.val);
- if ("MODEL".equalsIgnoreCase(plan.getScopeType()) && plan.getScopeValue() != null) {
- try {
- wrapper.eq(Agv::getAgvModel, Long.valueOf(plan.getScopeValue()));
- } catch (NumberFormatException ignore) {
- log.warn("Guarantee[{}] invalid scopeValue {}", plan.getName(), plan.getScopeValue());
- }
- }
- return agvService.list(wrapper);
- }
-
- @Data
- private static class CapacitySnapshot {
- private final int availableCount;
- private final List<ChargeCandidate> candidates;
- }
-
- @Data
- @AllArgsConstructor
- private static class ChargeCandidate {
- private Agv agv;
- private AgvDetail detail;
- }
-}
--
Gitblit v1.9.1