From 3714efbc9bcadabb5d216c59dd45704acc88a429 Mon Sep 17 00:00:00 2001 From: yahaozhang Date: Sun, 14 Sep 2025 14:55:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=88=86=E9=85=8D=E6=9C=8D=E5=8A=A1=EF=BC=8C=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=A4=84=E7=90=86=E8=B6=85=E6=97=B6=E9=93=BE=E6=8E=A5=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E7=8A=B6=E6=80=81=E5=B9=B6=E8=AE=B0=E5=BD=95=E5=8E=86?= =?UTF-8?q?=E5=8F=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/link/DeviceAllocationService.java | 98 +++++++++++++++++-- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/gameplatform/server/service/link/DeviceAllocationService.java b/src/main/java/com/gameplatform/server/service/link/DeviceAllocationService.java index 42fcc5b..7a74a26 100644 --- a/src/main/java/com/gameplatform/server/service/link/DeviceAllocationService.java +++ b/src/main/java/com/gameplatform/server/service/link/DeviceAllocationService.java @@ -3,10 +3,15 @@ package com.gameplatform.server.service.link; import com.gameplatform.server.mapper.agent.LinkTaskMapper; import com.gameplatform.server.model.entity.agent.LinkTask; import com.gameplatform.server.service.cooldown.MemoryMachineCooldownService; +import com.gameplatform.server.mapper.history.LinkTaskStatusHistoryMapper; +import com.gameplatform.server.model.entity.history.LinkTaskStatusHistory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -22,11 +27,14 @@ public class DeviceAllocationService { private final MemoryMachineCooldownService machineCooldownService; private final LinkTaskMapper linkTaskMapper; + private final LinkTaskStatusHistoryMapper statusHistoryMapper; public DeviceAllocationService(MemoryMachineCooldownService machineCooldownService, - LinkTaskMapper linkTaskMapper) { + LinkTaskMapper linkTaskMapper, + LinkTaskStatusHistoryMapper statusHistoryMapper) { this.machineCooldownService = machineCooldownService; this.linkTaskMapper = linkTaskMapper; + this.statusHistoryMapper = statusHistoryMapper; } /** @@ -36,6 +44,7 @@ public class DeviceAllocationService { * @param reason 分配原因 * @return 分配成功的设备ID,如果所有设备都被占用则返回null */ + @Transactional public String allocateDevice(List availableDevices, Long linkTaskId, String reason) { if (availableDevices == null || availableDevices.isEmpty()) { log.warn("设备分配失败:没有可用设备"); @@ -84,15 +93,88 @@ public class DeviceAllocationService { List availableDevices = new ArrayList<>(); for (String deviceId : devices) { - // 检查设备是否被其他链接任务占用(USING、LOGGED_IN状态) - List occupiedTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "USING"); - occupiedTasks.addAll(linkTaskMapper.findByMachineIdAndStatus(deviceId, "LOGGED_IN")); - - if (occupiedTasks.isEmpty()) { + // 检查设备是否被其他链接任务占用(USING、LOGGED_IN状态),并自动清理超时占用 + List usingTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "USING"); + List loggedInTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "LOGGED_IN"); + + LocalDateTime now = LocalDateTime.now(); + List stillOccupied = new ArrayList<>(); + + // USING 超过10分钟未选择区 -> EXPIRED,并写入历史 + for (LinkTask task : usingTasks) { + try { + LocalDateTime firstSelectAt = task.getFirstRegionSelectAt(); + boolean shouldExpire = firstSelectAt != null && firstSelectAt.isBefore(now.minusMinutes(10)); + if (shouldExpire) { + String prev = task.getStatus(); + task.setStatus("EXPIRED"); + task.setUpdatedAt(now); + int updated = linkTaskMapper.update(task); + if (updated > 0) { + try { + Integer sinceLoginSeconds = null; + if (task.getLoginAt() != null) { + sinceLoginSeconds = (int) Duration.between(task.getLoginAt(), now).getSeconds(); + } + statusHistoryMapper.insert(new LinkTaskStatusHistory( + task.getId(), task.getCodeNo(), deviceId, + prev, "EXPIRED", "DEVICE_ALLOCATION", "usingTimeoutExpire10m", + sinceLoginSeconds, null + )); + } catch (Exception ignore) {} + log.info("自动过期USING链接:codeNo={}, device={}, firstRegionSelectAt={}, 超过10分钟", task.getCodeNo(), deviceId, firstSelectAt); + } else { + stillOccupied.add(task); + } + } else { + stillOccupied.add(task); + } + } catch (Exception e) { + log.warn("检查/更新USING任务超时失败,保持占用:codeNo={}, device={}, err={}", task.getCodeNo(), deviceId, e.getMessage()); + stillOccupied.add(task); + } + } + + // LOGGED_IN 距离上次更新超过30分钟 -> COMPLETED,并写入历史 + for (LinkTask task : loggedInTasks) { + try { + LocalDateTime updatedAt = task.getUpdatedAt(); + boolean shouldComplete = updatedAt != null && updatedAt.isBefore(now.minusMinutes(30)); + if (shouldComplete) { + String prev = task.getStatus(); + task.setStatus("COMPLETED"); + task.setUpdatedAt(now); + int updated = linkTaskMapper.update(task); + if (updated > 0) { + try { + Integer sinceLoginSeconds = null; + if (task.getLoginAt() != null) { + sinceLoginSeconds = (int) Duration.between(task.getLoginAt(), now).getSeconds(); + } + statusHistoryMapper.insert(new LinkTaskStatusHistory( + task.getId(), task.getCodeNo(), deviceId, + prev, "COMPLETED", "DEVICE_ALLOCATION", "autoCompleteAfter30m", + sinceLoginSeconds, null + )); + } catch (Exception ignore) {} + log.info("自动完成LOGGED_IN链接:codeNo={}, device={}, updatedAt={}, 超过30分钟", task.getCodeNo(), deviceId, updatedAt); + } else { + stillOccupied.add(task); + } + } else { + stillOccupied.add(task); + } + } catch (Exception e) { + log.warn("检查/更新LOGGED_IN任务超时失败,保持占用:codeNo={}, device={}, err={}", task.getCodeNo(), deviceId, e.getMessage()); + stillOccupied.add(task); + } + } + + if (stillOccupied.isEmpty()) { availableDevices.add(deviceId); } else { - log.debug("设备{}被其他链接任务占用,占用任务数={}", deviceId, occupiedTasks.size()); - for (LinkTask occupiedTask : occupiedTasks) { + log.debug("设备{}被其他链接任务占用,占用任务数={}", deviceId, stillOccupied.size()); + for (LinkTask occupiedTask : stillOccupied) { log.debug("占用设备{}的链接:codeNo={}, status={}, 任务ID={}", deviceId, occupiedTask.getCodeNo(), occupiedTask.getStatus(), occupiedTask.getId()); }