feat: 增强设备分配服务,自动处理超时链接任务状态并记录历史

This commit is contained in:
yahaozhang
2025-09-14 14:55:24 +08:00
parent 2ee58a9402
commit 3714efbc9b

View File

@@ -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<String> availableDevices, Long linkTaskId, String reason) {
if (availableDevices == null || availableDevices.isEmpty()) {
log.warn("设备分配失败:没有可用设备");
@@ -84,15 +93,88 @@ public class DeviceAllocationService {
List<String> availableDevices = new ArrayList<>();
for (String deviceId : devices) {
// 检查设备是否被其他链接任务占用USING、LOGGED_IN状态
List<LinkTask> occupiedTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "USING");
occupiedTasks.addAll(linkTaskMapper.findByMachineIdAndStatus(deviceId, "LOGGED_IN"));
if (occupiedTasks.isEmpty()) {
// 检查设备是否被其他链接任务占用USING、LOGGED_IN状态,并自动清理超时占用
List<LinkTask> usingTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "USING");
List<LinkTask> loggedInTasks = linkTaskMapper.findByMachineIdAndStatus(deviceId, "LOGGED_IN");
LocalDateTime now = LocalDateTime.now();
List<LinkTask> 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());
}