|
|
@@ -18,6 +18,7 @@ import org.springframework.context.event.EventListener;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.util.concurrent.DelayQueue;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
import java.util.concurrent.Executors;
|
|
|
@@ -88,7 +89,6 @@ public class StopChargeDelayJob implements DelayService<DelayChargeOrder> {
|
|
|
// 启动线程池中的所有线程处理延迟队列
|
|
|
for (int i = 0; i < MAX_THREAD_COUNT; i++) {
|
|
|
executor.execute(() -> {
|
|
|
- ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null); // 初始化为空值,避免使用new ThreadLocal()
|
|
|
log.info("预约停止充电处理线程:{}", Thread.currentThread().getName());
|
|
|
while (true) {
|
|
|
DelayedItem<DelayChargeOrder> delayedItem = null;
|
|
|
@@ -98,17 +98,19 @@ public class StopChargeDelayJob implements DelayService<DelayChargeOrder> {
|
|
|
log.info("出队预约停止充电订单:{}, 队列剩余:{}", delayedItem.data.getStartChargeSeq(), STOP_DELAY_QUEUE.size());
|
|
|
// 停止充电
|
|
|
var order = delayedItem.data;
|
|
|
- threadLocal.set(order.getStartChargeSeq());
|
|
|
- // 查询该设备最新订单是否是当前预约订单,是则按计划停止(优化:使用LIMIT 1代替查询所有)
|
|
|
+ // 查询该设备最新一笔进行中的订单,与预约订单比对,防止已取消订单干扰匹配
|
|
|
var currentChargeOrder = chargeOrderService.lambdaQuery()
|
|
|
.eq(ChargeOrder::getConnectorId, order.getConnectorId())
|
|
|
+ .in(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中, ChargeOrder.CHARGE_STATUS_启动中, ChargeOrder.CHARGE_STATUS_充电中, ChargeOrder.CHARGE_STATUS_停止中)
|
|
|
.orderByDesc(ChargeOrder::getCreateTime)
|
|
|
.last("LIMIT 1")
|
|
|
.one();
|
|
|
- if (currentChargeOrder.getStartChargeSeq().equals(order.getStartChargeSeq())) {
|
|
|
+ if (currentChargeOrder == null) {
|
|
|
+ // 设备已无进行中的订单,订单可能已被人工处理,无需停止,跳过即可
|
|
|
+ log.warn("预约充电停止跳过:设备{}当前无进行中的订单,预约订单:{}", order.getConnectorId(), order.getStartChargeSeq());
|
|
|
+ } else if (currentChargeOrder.getStartChargeSeq().equals(order.getStartChargeSeq())) {
|
|
|
chargeService.queryStopCharge(order.getUserId(), order.getConnectorId());
|
|
|
log.info("预约充电停止成功:用户:{}, 订单号:{}, 预约停止时间:{}", order.getUserId(), order.getStartChargeSeq(), order.getEndTime());
|
|
|
-
|
|
|
} else {
|
|
|
log.error("预约充电停止异常:订单不匹配:原订单:{}, 当前设备最新订单:{}", order.getStartChargeSeq(), currentChargeOrder.getStartChargeSeq());
|
|
|
throw new BusinessException("预约充电停止异常");
|
|
|
@@ -120,10 +122,18 @@ public class StopChargeDelayJob implements DelayService<DelayChargeOrder> {
|
|
|
// 线程被中断,退出循环
|
|
|
break;
|
|
|
} else {
|
|
|
- log.info("预约停止充电失败,订单号:{}", threadLocal.get(), e);
|
|
|
+ log.info("预约停止充电失败,订单号:{}", delayedItem == null ? null : delayedItem.data.getStartChargeSeq(), e);
|
|
|
+ // 失败重新入队延迟重试,防止订单一直挂“充电中”;超过预约结束时间2小时后放弃并告警
|
|
|
+ if (delayedItem != null) {
|
|
|
+ var data = delayedItem.data;
|
|
|
+ if (LocalDateTime.now().isBefore(data.getEndTime().plusHours(2))) {
|
|
|
+ STOP_DELAY_QUEUE.add(new DelayedItem<>(data, LocalDateTime.now().plusSeconds(60)));
|
|
|
+ log.warn("预约停止充电重试入队,订单号:{},60秒后重试", data.getStartChargeSeq());
|
|
|
+ } else {
|
|
|
+ log.error("预约停止充电多次失败,放弃重试,订单号:{},请人工核查", data.getStartChargeSeq());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- } finally {
|
|
|
- threadLocal.remove();
|
|
|
}
|
|
|
}
|
|
|
});
|