`.tasks/` 文件仓库。 这里仅负责 JSON 文件读写,任务状态流转放在 TaskService 中,避免存储层知道业务规则。
| 17 | * 这里仅负责 JSON 文件读写,任务状态流转放在 TaskService 中,避免存储层知道业务规则。 |
| 18 | */ |
| 19 | public class TaskStore { |
| 20 | |
| 21 | private final File tasksDir; |
| 22 | |
| 23 | public TaskStore(File workdir) { |
| 24 | this.tasksDir = new File(workdir, ".tasks"); |
| 25 | } |
| 26 | |
| 27 | public TaskRecord save(TaskRecord task) { |
| 28 | ensureTasksDir(); |
| 29 | File file = taskFile(task.getId()); |
| 30 | try { |
| 31 | Files.writeString(file.toPath(), JSON.toJSONString(task, true), StandardCharsets.UTF_8); |
| 32 | } |
| 33 | catch (IOException e) { |
| 34 | throw new IllegalStateException("Failed to write task: " + file, e); |
| 35 | } |
| 36 | return task; |
| 37 | } |
| 38 | |
| 39 | public TaskRecord load(String taskId) { |
| 40 | File file = taskFile(taskId); |
| 41 | if (!file.isFile()) { |
| 42 | throw new IllegalArgumentException("Task " + taskId + " not found"); |
| 43 | } |
| 44 | try { |
| 45 | return JSON.parseObject(Files.readString(file.toPath(), StandardCharsets.UTF_8), TaskRecord.class); |
| 46 | } |
| 47 | catch (IOException e) { |
| 48 | throw new IllegalStateException("Failed to read task: " + file, e); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | public boolean exists(String taskId) { |
| 53 | if (!isSafeTaskId(taskId)) { |
| 54 | return false; |
| 55 | } |
| 56 | return taskFile(taskId).isFile(); |
| 57 | } |
| 58 | |
| 59 | public List<TaskRecord> list() { |
| 60 | ensureTasksDir(); |
| 61 | File[] files = tasksDir.listFiles(file -> file.isFile() |
| 62 | && file.getName().startsWith("task_") |
| 63 | && file.getName().endsWith(".json")); |
| 64 | List<TaskRecord> tasks = new ArrayList<>(); |
| 65 | if (files == null) { |
| 66 | return tasks; |
| 67 | } |
| 68 | Arrays.sort(files); |
| 69 | for (File file : files) { |
| 70 | try { |
| 71 | tasks.add(JSON.parseObject(Files.readString(file.toPath(), StandardCharsets.UTF_8), |
| 72 | TaskRecord.class)); |
| 73 | } |
| 74 | catch (RuntimeException | IOException e) { |
| 75 | System.out.println("Skip task " + file.getName() + ": " + e.getMessage()); |
| 76 | } |
nothing calls this directly
no outgoing calls
no test coverage detected