refactor(tasks): replace generic task mutation api

This commit is contained in:
Vincent Koc
2026-03-30 12:49:10 +09:00
parent 16df3de098
commit c7106c4285
6 changed files with 112 additions and 19 deletions

View File

@@ -8,9 +8,10 @@ import {
ensureTaskRegistryReady,
getTaskById,
listTaskRecords,
markTaskLostById,
maybeDeliverTaskTerminalUpdate,
resolveTaskForLookupToken,
updateTaskRecordById,
setTaskCleanupAfterById,
} from "./task-registry.js";
import { summarizeTaskRecords } from "./task-registry.summary.js";
import type { TaskRecord, TaskRegistrySummary } from "./task-registry.types.js";
@@ -110,8 +111,8 @@ function resolveCleanupAfter(task: TaskRecord): number {
function markTaskLost(task: TaskRecord, now: number): TaskRecord {
const cleanupAfter = task.cleanupAfter ?? projectTaskLost(task, now).cleanupAfter;
const updated =
updateTaskRecordById(task.taskId, {
status: "lost",
markTaskLostById({
taskId: task.taskId,
endedAt: task.endedAt ?? now,
lastEventAt: now,
error: task.error ?? "backing session missing",
@@ -207,7 +208,8 @@ export function runTaskRegistryMaintenance(): TaskRegistryMaintenanceSummary {
}
if (
shouldStampCleanupAfter(task) &&
updateTaskRecordById(task.taskId, {
setTaskCleanupAfterById({
taskId: task.taskId,
cleanupAfter: resolveCleanupAfter(task),
})
) {

View File

@@ -17,8 +17,9 @@ import {
maybeDeliverTaskTerminalUpdate,
resetTaskRegistryForTests,
resolveTaskForLookupToken,
setTaskProgressById,
setTaskTimingById,
updateTaskNotifyPolicyById,
updateTaskRecordById,
updateTaskStateByRunId,
} from "./task-registry.js";
import {
@@ -440,7 +441,8 @@ describe("task-registry", () => {
startedAt: 100,
});
updateTaskRecordById(findTaskByRunId("run-detail-leak")!.taskId, {
setTaskProgressById({
taskId: findTaskByRunId("run-detail-leak")!.taskId,
progressSummary:
"I am loading the local session context and checking helper command availability before writing the file.",
});
@@ -800,7 +802,8 @@ describe("task-registry", () => {
status: "running",
deliveryStatus: "pending",
});
updateTaskRecordById(task.taskId, {
setTaskTimingById({
taskId: task.taskId,
lastEventAt: Date.now() - 10 * 60_000,
});
@@ -832,7 +835,8 @@ describe("task-registry", () => {
status: "running",
deliveryStatus: "pending",
});
updateTaskRecordById(task.taskId, {
setTaskTimingById({
taskId: task.taskId,
lastEventAt: now - 10 * 60_000,
});
@@ -864,7 +868,8 @@ describe("task-registry", () => {
deliveryStatus: "not_applicable",
startedAt: Date.now() - 9 * 24 * 60 * 60_000,
});
updateTaskRecordById(task.taskId, {
setTaskTimingById({
taskId: task.taskId,
endedAt: Date.now() - 8 * 24 * 60 * 60_000,
lastEventAt: Date.now() - 8 * 24 * 60 * 60_000,
});

View File

@@ -686,12 +686,96 @@ export async function maybeDeliverTaskStateChangeUpdate(
}
}
export function updateTaskRecordById(
taskId: string,
patch: Partial<TaskRecord>,
): TaskRecord | null {
export function setTaskProgressById(params: {
taskId: string;
progressSummary?: string | null;
lastEventAt?: number;
}): TaskRecord | null {
ensureTaskRegistryReady();
return updateTask(taskId, patch);
const patch: Partial<TaskRecord> = {};
if (params.progressSummary !== undefined) {
patch.progressSummary = normalizeTaskSummary(params.progressSummary);
}
if (params.lastEventAt != null) {
patch.lastEventAt = params.lastEventAt;
}
return updateTask(params.taskId, patch);
}
export function setTaskTimingById(params: {
taskId: string;
startedAt?: number;
endedAt?: number;
lastEventAt?: number;
}): TaskRecord | null {
ensureTaskRegistryReady();
const patch: Partial<TaskRecord> = {};
if (params.startedAt != null) {
patch.startedAt = params.startedAt;
}
if (params.endedAt != null) {
patch.endedAt = params.endedAt;
}
if (params.lastEventAt != null) {
patch.lastEventAt = params.lastEventAt;
}
return updateTask(params.taskId, patch);
}
export function setTaskCleanupAfterById(params: {
taskId: string;
cleanupAfter: number;
}): TaskRecord | null {
ensureTaskRegistryReady();
return updateTask(params.taskId, {
cleanupAfter: params.cleanupAfter,
});
}
export function markTaskTerminalById(params: {
taskId: string;
status: Extract<TaskStatus, "succeeded" | "failed" | "timed_out" | "cancelled">;
endedAt: number;
lastEventAt?: number;
error?: string;
terminalSummary?: string | null;
terminalOutcome?: TaskTerminalOutcome | null;
}): TaskRecord | null {
ensureTaskRegistryReady();
return updateTask(params.taskId, {
status: params.status,
endedAt: params.endedAt,
lastEventAt: params.lastEventAt ?? params.endedAt,
...(params.error !== undefined ? { error: params.error } : {}),
...(params.terminalSummary !== undefined
? { terminalSummary: normalizeTaskSummary(params.terminalSummary) }
: {}),
...(params.terminalOutcome !== undefined
? {
terminalOutcome: resolveTaskTerminalOutcome({
status: params.status,
terminalOutcome: params.terminalOutcome,
}),
}
: {}),
});
}
export function markTaskLostById(params: {
taskId: string;
endedAt: number;
lastEventAt?: number;
error?: string;
cleanupAfter?: number;
}): TaskRecord | null {
ensureTaskRegistryReady();
return updateTask(params.taskId, {
status: "lost",
endedAt: params.endedAt,
lastEventAt: params.lastEventAt ?? params.endedAt,
...(params.error !== undefined ? { error: params.error } : {}),
...(params.cleanupAfter !== undefined ? { cleanupAfter: params.cleanupAfter } : {}),
});
}
function updateTasksByRunId(runId: string, patch: Partial<TaskRecord>): TaskRecord[] {