fix(FN-3175): reduce dashboard log stalls

This commit is contained in:
gsxdsm
2026-05-02 08:05:33 -07:00
parent 207d9d2524
commit d787a16a79
16 changed files with 209 additions and 43 deletions

View File

@@ -2912,6 +2912,30 @@ describe("maintenance cycle concurrency", () => {
expect((manager as any).maintenanceRunning).toBe(false);
});
it("uses a passive WAL checkpoint during maintenance", async () => {
(vi.spyOn(manager as any, "pruneWorktrees").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "cleanupOrphans").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "cleanupOrphanedBranches").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "enforceWorktreeCap").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverCompletedTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverStaleIncompleteReviewTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverInterruptedMergingTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverMergeableReviewTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverMergedReviewTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverMisclassifiedFailures").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverNoProgressNoTaskDoneFailures").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverPartialProgressNoTaskDoneFailures").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverOrphanedExecutions").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverApprovedTriageTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverOrphanedPlanningTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "recoverGhostReviewTasks").mockResolvedValue(0) as any);
(vi.spyOn(manager as any, "archiveStaleDoneTasks").mockResolvedValue(0) as any);
await (manager as any).runMaintenance();
expect(store.walCheckpoint).toHaveBeenCalledWith("PASSIVE");
});
it("runs batch 1 operations in sequence (with isolation — one failure doesn't block others)", async () => {
let runningCount = 0;
let maxConcurrent = 0;

View File

@@ -179,7 +179,8 @@ export class AgentLogger {
*
* @param name - The tool name
* @param isError - Whether the tool execution resulted in an error
* @param result - Optional result value (persisted in full)
* @param result - Optional result value. Downstream storage may clip very
* large tool payloads to keep dashboard log views responsive.
*/
onToolEnd(name: string, isError: boolean, result?: unknown): void {
const type = isError ? "tool_error" : "tool_result";

View File

@@ -1844,12 +1844,12 @@ export class SelfHealingManager {
}
}
/** Run SQLite WAL checkpoint to reclaim disk space. */
/** Run a best-effort passive WAL checkpoint without forcing live writers to truncate. */
private checkpointWal(): void {
try {
const result = this.store.walCheckpoint();
const result = this.store.walCheckpoint("PASSIVE");
if (result.log > 0) {
log.log(`WAL checkpoint: ${result.checkpointed}/${result.log} pages checkpointed` +
log.log(`WAL checkpoint (passive): ${result.checkpointed}/${result.log} pages checkpointed` +
(result.busy > 0 ? ` (${result.busy} busy)` : ""));
}
} catch (err: unknown) { const errorMessage = err instanceof Error ? err.message : String(err);