| ... | ... | @@ -3,6 +3,7 @@ import { |
| 3 | 3 | ProjectId, |
| 4 | 4 | ProviderInstanceId, |
| 5 | 5 | RunId, |
| 6 | RuntimeRequestId, |
| 6 | 7 | ThreadId, |
| 7 | 8 | type OrchestrationV2ThreadShell, |
| 8 | 9 | } from "@t3tools/contracts"; |
| ... | ... | @@ -84,6 +85,47 @@ describe("V2 storage cleanup eligibility", () => { |
| 84 | 85 | }, |
| 85 | 86 | ); |
| 86 | 87 | |
| 88 | it.each(["idle", "completed", "interrupted", "failed", "cancelled", "rolled_back"] as const)( |
| 89 | "allows cleanup once its thread is %s", |
| 90 | (status) => { |
| 91 | expect(storageCleanupThreadIdle(candidateWithStatus(status), NOW_MS)).toBe(true); |
| 92 | }, |
| 93 | ); |
| 94 | |
| 95 | it.each(["completed", "interrupted", "cancelled", "rolled_back"] as const)( |
| 96 | "retains %s while background work is pending", |
| 97 | (status) => { |
| 98 | expect( |
| 99 | storageCleanupThreadIdle( |
| 100 | { |
| 101 | ...candidateWithStatus(status), |
| 102 | pendingBackgroundTasks: [{ taskId: "task-1", kind: "command" }], |
| 103 | }, |
| 104 | NOW_MS, |
| 105 | ), |
| 106 | ).toBe(false); |
| 107 | }, |
| 108 | ); |
| 109 | |
| 110 | it.each(["completed", "interrupted", "cancelled", "rolled_back"] as const)( |
| 111 | "retains %s while a runtime request is pending", |
| 112 | (status) => { |
| 113 | expect( |
| 114 | storageCleanupThreadIdle( |
| 115 | { |
| 116 | ...candidateWithStatus(status), |
| 117 | pendingRuntimeRequest: { |
| 118 | id: RuntimeRequestId.make("request-1"), |
| 119 | kind: "command", |
| 120 | createdAt: at(0), |
| 121 | }, |
| 122 | }, |
| 123 | NOW_MS, |
| 124 | ), |
| 125 | ).toBe(false); |
| 126 | }, |
| 127 | ); |
| 128 | |
| 87 | 129 | it("retains an active run even if the shell status is idle", () => { |
| 88 | 130 | expect( |
| 89 | 131 | storageCleanupThreadIdle({ ...candidate(), activeRunId: RunId.make("run") }, NOW_MS), |