feat(web): 增强任务治理与系统诊断能力
新增任务持久化、筛选分页、取消任务、健康检查与 AI 输入校验,并完善前端历史管理交互与容错重试机制。补充对应单元测试,提升系统稳定性和可运维性。
This commit is contained in:
138
src/main/java/com/svnlog/web/service/TaskPersistenceService.java
Normal file
138
src/main/java/com/svnlog/web/service/TaskPersistenceService.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package com.svnlog.web.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.svnlog.web.model.TaskInfo;
|
||||
import com.svnlog.web.model.TaskStatus;
|
||||
|
||||
@Service
|
||||
public class TaskPersistenceService {
|
||||
|
||||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
public List<TaskInfo> load(Path storePath) throws IOException {
|
||||
if (storePath == null || !Files.exists(storePath) || !Files.isRegularFile(storePath)) {
|
||||
return new ArrayList<TaskInfo>();
|
||||
}
|
||||
|
||||
try (Reader reader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) {
|
||||
List<PersistedTaskInfo> persisted = gson.fromJson(
|
||||
reader,
|
||||
new TypeToken<List<PersistedTaskInfo>>() {
|
||||
}.getType()
|
||||
);
|
||||
if (persisted == null) {
|
||||
return new ArrayList<TaskInfo>();
|
||||
}
|
||||
|
||||
List<TaskInfo> result = new ArrayList<TaskInfo>();
|
||||
for (PersistedTaskInfo item : persisted) {
|
||||
result.add(toTaskInfo(item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public void save(Path storePath, Collection<TaskInfo> tasks) throws IOException {
|
||||
if (storePath == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (storePath.getParent() != null) {
|
||||
Files.createDirectories(storePath.getParent());
|
||||
}
|
||||
|
||||
List<PersistedTaskInfo> persisted = new ArrayList<PersistedTaskInfo>();
|
||||
if (tasks != null) {
|
||||
for (TaskInfo task : tasks) {
|
||||
persisted.add(fromTaskInfo(task));
|
||||
}
|
||||
}
|
||||
|
||||
try (Writer writer = Files.newBufferedWriter(storePath, StandardCharsets.UTF_8)) {
|
||||
gson.toJson(persisted, writer);
|
||||
}
|
||||
}
|
||||
|
||||
private PersistedTaskInfo fromTaskInfo(TaskInfo task) {
|
||||
PersistedTaskInfo info = new PersistedTaskInfo();
|
||||
info.taskId = task.getTaskId();
|
||||
info.type = task.getType();
|
||||
info.status = task.getStatus() == null ? null : task.getStatus().name();
|
||||
info.progress = task.getProgress();
|
||||
info.message = task.getMessage();
|
||||
info.error = task.getError();
|
||||
info.createdAt = toString(task.getCreatedAt());
|
||||
info.updatedAt = toString(task.getUpdatedAt());
|
||||
info.files = new ArrayList<String>(task.getFiles());
|
||||
return info;
|
||||
}
|
||||
|
||||
private TaskInfo toTaskInfo(PersistedTaskInfo persisted) {
|
||||
TaskInfo task = new TaskInfo();
|
||||
task.setTaskId(persisted.taskId);
|
||||
task.setType(persisted.type);
|
||||
task.setStatus(parseStatus(persisted.status));
|
||||
task.setProgress(persisted.progress);
|
||||
task.setMessage(persisted.message);
|
||||
task.setError(persisted.error);
|
||||
task.setCreatedAt(parseInstant(persisted.createdAt));
|
||||
task.setUpdatedAt(parseInstant(persisted.updatedAt));
|
||||
if (persisted.files != null) {
|
||||
task.getFiles().addAll(persisted.files);
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private Instant parseInstant(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return Instant.now();
|
||||
}
|
||||
try {
|
||||
return Instant.parse(value);
|
||||
} catch (Exception e) {
|
||||
return Instant.now();
|
||||
}
|
||||
}
|
||||
|
||||
private String toString(Instant value) {
|
||||
return value == null ? Instant.now().toString() : value.toString();
|
||||
}
|
||||
|
||||
private TaskStatus parseStatus(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return TaskStatus.FAILED;
|
||||
}
|
||||
try {
|
||||
return TaskStatus.valueOf(value);
|
||||
} catch (Exception e) {
|
||||
return TaskStatus.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
private static class PersistedTaskInfo {
|
||||
private String taskId;
|
||||
private String type;
|
||||
private String status;
|
||||
private int progress;
|
||||
private String message;
|
||||
private String error;
|
||||
private String createdAt;
|
||||
private String updatedAt;
|
||||
private List<String> files;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user