diff --git a/packages/openworkflow/client.test.ts b/packages/openworkflow/client.test.ts index 0e154cb8..533aeab7 100644 --- a/packages/openworkflow/client.test.ts +++ b/packages/openworkflow/client.test.ts @@ -412,6 +412,33 @@ describe("OpenWorkflow", () => { expect(workflowRun?.finishedAt).not.toBeNull(); }); + test("cancels workflow run via client by ID", async () => { + const backend = await createBackend(); + const client = new OpenWorkflow({ backend }); + + const workflow = client.defineWorkflow({ name: "cancel-test" }, noopFn); + const handle = await workflow.run({ value: 1 }); + + await client.cancelWorkflowRun(handle.workflowRun.id); + + const workflowRun = await backend.getWorkflowRun({ + workflowRunId: handle.workflowRun.id, + }); + expect(workflowRun?.status).toBe("canceled"); + expect(workflowRun?.finishedAt).not.toBeNull(); + }); + + test("throws when canceling a non-existent workflow run", async () => { + const backend = await createBackend(); + const client = new OpenWorkflow({ backend }); + + const nonExistentId = randomUUID(); + + await expect(client.cancelWorkflowRun(nonExistentId)).rejects.toThrow( + `Workflow run ${nonExistentId} does not exist`, + ); + }); + describe("defineWorkflowSpec / implementWorkflow API", () => { test("defineWorkflowSpec returns a spec that can be used to schedule runs", async () => { const backend = await createBackend(); diff --git a/packages/openworkflow/client.ts b/packages/openworkflow/client.ts index 6be212b1..ebdd89e1 100644 --- a/packages/openworkflow/client.ts +++ b/packages/openworkflow/client.ts @@ -157,6 +157,20 @@ export class OpenWorkflow { return new RunnableWorkflow(this, workflow); } + + /** + * Cancels the workflow run with the given ID. Only workflow runs in pending, running, or sleeping + * status can be canceled. + * @param workflowRunId - The ID of the workflow run to cancel + * @returns Promise + * @example + * ```ts + * await ow.cancelWorkflowRun("123"); + * ``` + */ + async cancelWorkflowRun(workflowRunId: string): Promise { + await this.backend.cancelWorkflowRun({ workflowRunId }); + } } /**