Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quiet-fibers-finish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agents": patch
---

Preserve a legacy `runFiber` result when deleting its bookkeeping row fails. The cleanup error is logged and the row is left for the existing recovery pass instead of replacing the fiber body's outcome.
29 changes: 18 additions & 11 deletions packages/agents/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4657,17 +4657,24 @@ export class Agent<
}
} finally {
this._runFiberActiveFibers.delete(id);
this._withAgentSpan(
"finalize_fiber",
"fiber",
{
"cloudflare.agents.fiber.id": id,
"cloudflare.agents.fiber.name": name
},
() => {
this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;
}
);
try {
this._withAgentSpan(
"finalize_fiber",
"fiber",
{
"cloudflare.agents.fiber.id": id,
"cloudflare.agents.fiber.name": name
},
() => {
this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;
}
);
} catch (error) {
console.error(
`[Agent] Failed to finalize fiber "${name}" (${id}); leaving run row for recovery:`,
error
);
}
dispose();
if (root && registeredFacetRun) {
try {
Expand Down
17 changes: 17 additions & 0 deletions packages/agents/src/tests/agents/run-fiber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,23 @@ export class TestRunFiberAgent extends Agent {
});
}

async runWithFailingCleanup(value: string): Promise<string> {
this.sql`
CREATE TRIGGER fail_run_fiber_cleanup
BEFORE DELETE ON cf_agents_runs
WHEN OLD.name = 'cleanup-failure'
BEGIN
SELECT RAISE(FAIL, 'simulated fiber cleanup failure');
END
`;

try {
return await this.runFiber("cleanup-failure", async () => value);
} finally {
this.sql`DROP TRIGGER fail_run_fiber_cleanup`;
}
}

async runWithCheckpoint(steps: string[]): Promise<string[]> {
return this.runFiber("checkpoint", async (ctx) => {
const completed: string[] = [];
Expand Down
15 changes: 15 additions & 0 deletions packages/agents/src/tests/run-fiber.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ describe("runFiber", () => {
expect(log).toContain("executed:hello");
});

it("preserves a successful result when fiber cleanup fails", async () => {
const agent = await getAgentByName(
env.TestRunFiberAgent,
"run-cleanup-failure"
);

await expect(agent.runWithFailingCleanup("completed")).resolves.toBe(
"completed"
);
expect((await agent.getRunningFiberCount()) as unknown as number).toBe(1);

await agent.triggerRecoveryCheck();
expect((await agent.getRunningFiberCount()) as unknown as number).toBe(0);
});

it("should delete the fiber row on completion", async () => {
const agent = await getAgentByName(env.TestRunFiberAgent, "run-cleanup");

Expand Down
Loading