task-63: 进度快照写入最小更新间隔节流(终态豁免+删除清理跟踪)

This commit is contained in:
2026-08-30 18:28:15 +08:00
parent a9cee8e9a1
commit 9c9b8a6078
2 changed files with 239 additions and 0 deletions
@@ -7,19 +7,28 @@ import com.nanri.aiimage.common.exception.BusinessException;
import com.nanri.aiimage.modules.task.mapper.TaskProgressSnapshotMapper;
import com.nanri.aiimage.modules.task.model.entity.TaskProgressSnapshotEntity;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Service
@RequiredArgsConstructor
public class TaskProgressSnapshotService {
private static final Set<String> TERMINAL_STATUSES = Set.of("SUCCESS", "FAILED", "CANCELLED", "CANCELED");
private final TaskProgressSnapshotMapper taskProgressSnapshotMapper;
private final ObjectMapper objectMapper;
private final ConcurrentHashMap<String, Long> lastWriteAtMillis = new ConcurrentHashMap<>();
@Value("${aiimage.task-progress-snapshot.min-update-interval-ms:500}")
private long minUpdateIntervalMillis = 500;
@Transactional
public void save(Long taskId,
@@ -54,6 +63,7 @@ public class TaskProgressSnapshotService {
entity.setUpdatedAt(now);
try {
taskProgressSnapshotMapper.insert(entity);
touchLastWrite(taskId, moduleType, status);
return;
} catch (DuplicateKeyException ignored) {
existing = find(taskId, moduleType);
@@ -66,6 +76,9 @@ public class TaskProgressSnapshotService {
currentScopeKey, message, snapshotJson)) {
return;
}
if (shouldThrottle(taskId, moduleType, status)) {
return;
}
taskProgressSnapshotMapper.update(null, new LambdaUpdateWrapper<TaskProgressSnapshotEntity>()
.eq(TaskProgressSnapshotEntity::getId, existing.getId())
.set(TaskProgressSnapshotEntity::getStatus, status)
@@ -77,6 +90,31 @@ public class TaskProgressSnapshotService {
.set(TaskProgressSnapshotEntity::getMessage, message)
.set(TaskProgressSnapshotEntity::getSnapshotJson, snapshotJson)
.set(TaskProgressSnapshotEntity::getUpdatedAt, now));
touchLastWrite(taskId, moduleType, status);
}
private boolean shouldThrottle(Long taskId, String moduleType, String status) {
if (TERMINAL_STATUSES.contains(status)) {
return false;
}
long interval = Math.max(0L, minUpdateIntervalMillis);
if (interval <= 0L) {
return false;
}
Long lastWrite = lastWriteAtMillis.get(cacheKey(taskId, moduleType));
return lastWrite != null && System.currentTimeMillis() - lastWrite < interval;
}
private void touchLastWrite(Long taskId, String moduleType, String status) {
if (TERMINAL_STATUSES.contains(status)) {
lastWriteAtMillis.remove(cacheKey(taskId, moduleType));
return;
}
lastWriteAtMillis.put(cacheKey(taskId, moduleType), System.currentTimeMillis());
}
private static String cacheKey(Long taskId, String moduleType) {
return taskId + ":" + moduleType;
}
private boolean isUnchanged(TaskProgressSnapshotEntity existing,
@@ -116,6 +154,7 @@ public class TaskProgressSnapshotService {
taskProgressSnapshotMapper.delete(new LambdaQueryWrapper<TaskProgressSnapshotEntity>()
.eq(TaskProgressSnapshotEntity::getTaskId, taskId)
.eq(TaskProgressSnapshotEntity::getModuleType, moduleType));
lastWriteAtMillis.remove(cacheKey(taskId, moduleType));
}
private String writeJson(Object value) {