diff --git a/docs.json b/docs.json index 8020cce5..521e0b2e 100644 --- a/docs.json +++ b/docs.json @@ -155,6 +155,12 @@ "redis/sdks/ts/commands/auth/ping" ] }, + { + "group": "Connection", + "pages": [ + "redis/sdks/ts/commands/connection/client_setinfo" + ] + }, { "group": "Bitmap", "pages": [ @@ -209,6 +215,8 @@ "redis/sdks/ts/commands/hash/hexpiretime", "redis/sdks/ts/commands/hash/hget", "redis/sdks/ts/commands/hash/hgetall", + "redis/sdks/ts/commands/hash/hgetdel", + "redis/sdks/ts/commands/hash/hgetex", "redis/sdks/ts/commands/hash/hincrby", "redis/sdks/ts/commands/hash/hincrbyfloat", "redis/sdks/ts/commands/hash/hkeys", @@ -217,6 +225,7 @@ "redis/sdks/ts/commands/hash/hrandfield", "redis/sdks/ts/commands/hash/hscan", "redis/sdks/ts/commands/hash/hset", + "redis/sdks/ts/commands/hash/hsetex", "redis/sdks/ts/commands/hash/hpersist", "redis/sdks/ts/commands/hash/hpexpire", "redis/sdks/ts/commands/hash/hpexpireat", @@ -353,10 +362,12 @@ "group": "Stream", "pages": [ "redis/sdks/ts/commands/stream/xack", + "redis/sdks/ts/commands/stream/xackdel", "redis/sdks/ts/commands/stream/xadd", "redis/sdks/ts/commands/stream/xautoclaim", "redis/sdks/ts/commands/stream/xclaim", "redis/sdks/ts/commands/stream/xdel", + "redis/sdks/ts/commands/stream/xdelex", "redis/sdks/ts/commands/stream/xgroup", "redis/sdks/ts/commands/stream/xinfo", "redis/sdks/ts/commands/stream/xlen", @@ -423,6 +434,12 @@ "redis/sdks/py/commands/auth/ping" ] }, + { + "group": "Connection", + "pages": [ + "redis/sdks/py/commands/connection/client_setinfo" + ] + }, { "group": "Bitmap", "pages": [ @@ -465,6 +482,8 @@ "redis/sdks/py/commands/hash/hexpiretime", "redis/sdks/py/commands/hash/hget", "redis/sdks/py/commands/hash/hgetall", + "redis/sdks/py/commands/hash/hgetdel", + "redis/sdks/py/commands/hash/hgetex", "redis/sdks/py/commands/hash/hincrby", "redis/sdks/py/commands/hash/hincrbyfloat", "redis/sdks/py/commands/hash/hkeys", @@ -479,6 +498,7 @@ "redis/sdks/py/commands/hash/hpexpiretime", "redis/sdks/py/commands/hash/hpttl", "redis/sdks/py/commands/hash/hmset", + "redis/sdks/py/commands/hash/hsetex", "redis/sdks/py/commands/hash/hsetnx", "redis/sdks/py/commands/hash/hstrlen", "redis/sdks/py/commands/hash/httl", @@ -611,10 +631,12 @@ "group": "Stream", "pages": [ "redis/sdks/py/commands/stream/xack", + "redis/sdks/py/commands/stream/xackdel", "redis/sdks/py/commands/stream/xadd", "redis/sdks/py/commands/stream/xautoclaim", "redis/sdks/py/commands/stream/xclaim", "redis/sdks/py/commands/stream/xdel", + "redis/sdks/py/commands/stream/xdelex", "redis/sdks/py/commands/stream/xgroup_create", "redis/sdks/py/commands/stream/xgroup_createconsumer", "redis/sdks/py/commands/stream/xgroup_delconsumer", @@ -1047,8 +1069,8 @@ { "group": "REST API", "openapi": { - "source": "qstash/openapi.yaml", - "directory": "qstash/api-refence" + "source": "qstash/openapi.yaml", + "directory": "qstash/api-refence" }, "pages": [ "qstash/api/authentication", @@ -1190,6 +1212,7 @@ "group": "client.dlq", "pages": [ "workflow/basics/client/dlq/list", + "workflow/basics/client/dlq/delete", "workflow/basics/client/dlq/restart", "workflow/basics/client/dlq/resume", "workflow/basics/client/dlq/callback" @@ -1257,7 +1280,6 @@ "workflow/features/invoke/serveMany" ] } - ] }, { @@ -1590,9 +1612,7 @@ }, { "group": "Account", - "pages": [ - "GET /auditlogs" - ] + "pages": ["GET /auditlogs"] }, { "group": "DevOps", diff --git a/qstash/sdks/ts/examples/dlq.mdx b/qstash/sdks/ts/examples/dlq.mdx index 8670392c..c64a8fde 100644 --- a/qstash/sdks/ts/examples/dlq.mdx +++ b/qstash/sdks/ts/examples/dlq.mdx @@ -30,6 +30,94 @@ while (true) { import { Client } from "@upstash/qstash"; const client = new Client({ token: "" }); -const dlq = client.dlq; -await dlq.delete("dlqId"); + +await client.dlq.delete("dlqId"); +``` + +#### Delete multiple messages from the DLQ + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +// using an array of dlqIds +const result = await client.dlq.delete(["dlqId-1", "dlqId-2", "dlqId-3"]); + +// or using an object with dlqIds +const result2 = await client.dlq.delete({ + dlqIds: ["dlqId-1", "dlqId-2", "dlqId-3"], +}); + +console.log(result.deleted); // number of deleted messages +``` + +#### Delete DLQ messages with filters + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +// delete by label +const result = await client.dlq.delete({ label: "my-label" }); + +// delete with multiple filters +const result2 = await client.dlq.delete({ + url: "https://example.com", + label: "my-label", + fromDate: "1640995200000", + toDate: "1672531200000", +}); + +// delete all DLQ entries +await client.dlq.delete({ all: true }); +``` + +#### Retry a single message from the DLQ + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +const result = await client.dlq.retry("dlqId"); +``` + +#### Retry multiple messages from the DLQ + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +// using an array of dlqIds +const result = await client.dlq.retry(["dlqId-1", "dlqId-2"]); + +// or using an object with dlqIds +const result2 = await client.dlq.retry({ + dlqIds: ["dlqId-1", "dlqId-2"], +}); + +console.log(result.responses); // [{ messageId: "..." }, ...] +``` + +#### Retry DLQ messages with filters + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +// retry by label +const result = await client.dlq.retry({ label: "my-label" }); + +// retry with multiple filters +const result2 = await client.dlq.retry({ + url: "https://example.com", + label: "my-label", +}); + +// retry all DLQ entries +const result3 = await client.dlq.retry({ all: true }); ``` diff --git a/qstash/sdks/ts/examples/messages.mdx b/qstash/sdks/ts/examples/messages.mdx index 4ef72e5c..01e3d499 100644 --- a/qstash/sdks/ts/examples/messages.mdx +++ b/qstash/sdks/ts/examples/messages.mdx @@ -12,7 +12,7 @@ for accessing messages that are in the process of being delivered/retried. import { Client } from "@upstash/qstash"; const client = new Client({ token: "" }); -const messages = client.messages +const messages = client.messages; const msg = await messages.get("msgId"); ``` @@ -22,8 +22,8 @@ const msg = await messages.get("msgId"); import { Client } from "@upstash/qstash"; const client = new Client({ token: "" }); -const messages = client.messages -const msg = await messages.delete("msgId"); + +await client.messages.delete("msgId"); ``` #### Cancel messages in bulk @@ -35,13 +35,41 @@ import { Client } from "@upstash/qstash"; const client = new Client({ token: "" }); -// deleting two messages at once -await client.messages.deleteMany([ - "message-id-1", - "message-id-2", -]) +// cancel two messages at once +const result = await client.messages.delete(["message-id-1", "message-id-2"]); + +console.log(result.cancelled); // 2 + +// cancel all messages +const result2 = await client.messages.delete({ all: true }); +console.log(result2.cancelled); // number of cancelled messages +``` + +#### Cancel messages with filters + +Cancel all messages matching specific filters such as `flowControlKey`, `url`, `queueName`, and more. + +```typescript +import { Client } from "@upstash/qstash"; + +const client = new Client({ token: "" }); + +// cancel all messages with a specific flow control key +const result = await client.messages.delete({ + flowControlKey: "my-flow-key", +}); + +console.log(result.cancelled); // number of cancelled messages +// cancel with multiple filters +const result2 = await client.messages.delete({ + flowControlKey: "my-flow-key", + url: "https://example.com", + queueName: "my-queue", + label: "my-label", + fromDate: "1640995200000", + toDate: "1672531200000", +}); -// deleting all messages -await client.messages.deleteAll() +console.log(result2.cancelled); // number of cancelled messages ``` diff --git a/workflow/basics/client.mdx b/workflow/basics/client.mdx index 2760e409..ccdf699e 100644 --- a/workflow/basics/client.mdx +++ b/workflow/basics/client.mdx @@ -33,6 +33,7 @@ The client exposes a set of functions to manage workflow runs and inspect their - [client.getWaiters](/workflow/basics/client/waiters) - client.dlq - [client.dlq.list](/workflow/basics/client/dlq/list) + - [client.dlq.delete](/workflow/basics/client/dlq/delete) - [client.dlq.restart](/workflow/basics/client/dlq/restart) - [client.dlq.resume](/workflow/basics/client/dlq/resume) - [client.dlq.retryFailureFunction](/workflow/basics/client/dlq/callback) \ No newline at end of file diff --git a/workflow/basics/client/cancel.mdx b/workflow/basics/client/cancel.mdx index 87bdcda3..b0422ab3 100644 --- a/workflow/basics/client/cancel.mdx +++ b/workflow/basics/client/cancel.mdx @@ -5,36 +5,83 @@ title: "client.cancel" There are multiple ways you can cancel workflow runs: - Pass one or more workflow run ids to cancel them -- Pass a workflow url to cancel all runs starting with this url -- cancel all pending or active workflow runs +- Pass a workflow url to cancel all runs with this exact url +- Pass a url prefix to cancel all runs starting with this url +- Pass filters (label, date range) to cancel matching workflow runs +- Cancel all pending or active workflow runs (by calling without any parameters) ## Arguments - - The set of workflow run IDs you want to cancel + + The set of workflow run IDs you want to cancel. + + + + The exact URL of workflows you want to cancel. - The URL address you want to filter while canceling + The URL prefix to filter workflows while canceling. All workflows with URLs + starting with this prefix will be canceled. + + + + Cancel workflows with this label. + + + + Cancel workflows created after this date (Unix ms as string). + + + + Cancel workflows created before this date (Unix ms as string). - Whether you want to cancel all workflow runs without any filter. + + Deprecated: If no parameters are provided, all workflows will be cancelled + by default. + +## Returns + +Returns an object with the number of cancelled workflows: + +```ts +{ + cancelled: number; +} +``` + ## Usage ### Cancel a set of workflow runs ```ts // cancel a single workflow -await client.cancel({ ids: "" }); +const result = await client.cancel({ ids: "" }); +console.log(`Cancelled ${result.cancelled} workflow(s)`); // cancel a set of workflow runs -await client.cancel({ ids: ["", ""] }); +const result = await client.cancel({ + ids: ["", ""], +}); +console.log(`Cancelled ${result.cancelled} workflow(s)`); +``` + +### Cancel workflow runs with exact URL + +Cancel all workflow runs with a specific URL: + +```ts +const result = await client.cancel({ + workflowUrl: "https://your-endpoint.com/api/workflow", +}); +console.log(`Cancelled ${result.cancelled} workflow(s)`); ``` -### Cancel workflow runs with URL filter +### Cancel workflow runs with URL prefix If you have an endpoint called `https://your-endpoint.com` and you want to cancel all workflow runs on it, you can use `urlStartingWith`. @@ -43,14 +90,43 @@ Note that this will cancel workflows in all endpoints under `https://your-endpoint.com`. ```ts -await client.cancel({ urlStartingWith: "https://your-endpoint.com" }); +const result = await client.cancel({ + urlStartingWith: "https://your-endpoint.com", +}); +console.log(`Cancelled ${result.cancelled} workflow(s)`); +``` + +### Cancel workflow runs with filters + +Cancel all active workflows that match the provided filters: + +```ts +// cancel workflows with a specific label +const result = await client.cancel({ + label: "my-workflow-label", +}); + +// cancel workflows within a date range +const result = await client.cancel({ + fromDate: "1640995200000", + toDate: "1672531200000", +}); + +// combine multiple filters +const result = await client.cancel({ + label: "my-workflow-label", + fromDate: "1640995200000", + toDate: "1672531200000", +}); + +console.log(`Cancelled ${result.cancelled} workflow(s)`); ``` ### Cancel _all_ workflows -To cancel all pending and currently running workflows, you can -do it like this: +To cancel all pending and currently running workflows, simply call cancel without any parameters: ```ts -await client.cancel({ all: true }); +const result = await client.cancel({}); +console.log(`Cancelled ${result.cancelled} workflow(s)`); ``` diff --git a/workflow/basics/client/dlq/delete.mdx b/workflow/basics/client/dlq/delete.mdx new file mode 100644 index 00000000..d9adb0d2 --- /dev/null +++ b/workflow/basics/client/dlq/delete.mdx @@ -0,0 +1,82 @@ +--- +title: "client.dlq.delete" +--- + +The `dlq.delete` method removes one or more entries from the **Dead Letter Queue (DLQ)**. + +## Arguments + +The method accepts different argument types: + + + A single DLQ entry ID to delete. + + + + An array of DLQ entry IDs to delete. + + + + An object containing `dlqIds` to delete. + + + + One or more DLQ entry IDs. + + + + + + A filter object to delete matching DLQ entries. + + + + Delete entries with this label. + + + + Delete entries created after this date (Unix ms as string). + + + + Delete entries created before this date (Unix ms as string). + + + + Delete entries matching this workflow URL. + + + + Delete entries matching these workflow run IDs. + + + + +## Response + + + The number of DLQ entries that were deleted. + + +## Usage + + +```ts Single ID +await client.dlq.delete("dlq-12345"); +``` +```ts Multiple IDs +await client.dlq.delete(["dlq-12345", "dlq-67890"]); +``` +```ts Object with dlqIds +await client.dlq.delete({ + dlqIds: ["dlq-12345", "dlq-67890"], +}); +``` +```ts With Filters +await client.dlq.delete({ + label: "my-workflow-label", + fromDate: "1640995200000", + toDate: "1672531200000", +}); +``` + diff --git a/workflow/basics/client/dlq/restart.mdx b/workflow/basics/client/dlq/restart.mdx index 1e8b4020..ee58a001 100644 --- a/workflow/basics/client/dlq/restart.mdx +++ b/workflow/basics/client/dlq/restart.mdx @@ -2,11 +2,15 @@ title: "client.dlq.restart" --- -The `dlq.restart` method restarts one or more workflow runs from **Dead Letter Queue (DLQ)**. +The `dlq.restart` method restarts one or more workflow runs from the **Dead Letter Queue (DLQ)**. This allows you to reprocess workflow runs that previously failed after exhausting retries. +Can be called with DLQ IDs (with optional `flowControl` and `retries`), or with a filter object to restart matching entries. + ## Arguments +### DLQ ID mode + The DLQ entry ID or list of IDs to restart. Use the `dlqId` field from messages returned by `client.dlq.list()`. @@ -42,22 +46,41 @@ This allows you to reprocess workflow runs that previously failed after exhausti Defaults to `3` if not provided. -## Response +### Filter mode + + + Restart DLQ entries with this label. + -`client.dlq.restart()` returns one or more objects containing details of the restarted workflow run(s): + + Restart DLQ entries matching this workflow URL. + - - - - The ID of the new workflow run created from the restarted DLQ message. - + + Restart DLQ entries matching these workflow run IDs. + - - The Unix timestamp (in milliseconds) when the new workflow run was created. - + + Restart DLQ entries created after this date (Unix ms as string). + - + + Restart DLQ entries created before this date (Unix ms as string). + +## Response + +The return type depends on the input: +- **Single DLQ ID (string)**: Returns a single object +- **Array of DLQ IDs**: Returns an array of objects +- **Filter mode**: Returns an array of objects + + + The ID of the new workflow run created from the restarted DLQ message. + + + + The timestamp when the new workflow run was created. ## Usage @@ -66,8 +89,8 @@ This allows you to reprocess workflow runs that previously failed after exhausti ```ts Single const { messages } = await client.dlq.list(); -const response = await client.dlq.restart({ - dlqId: messages[0].dlqId, // Use the dlqId from the message +const run = await client.dlq.restart({ + dlqId: messages[0].dlqId, flowControl: { key: "my-flow-control-key", parallelism: 10, @@ -75,12 +98,24 @@ const response = await client.dlq.restart({ retries: 3, }); +console.log(run.workflowRunId); // ID of the restarted workflow run ``` ```ts Multiple -const responses = await client.dlq.restart({ +const runs = await client.dlq.restart({ dlqId: ["dlq-12345", "dlq-67890"], retries: 5, }); + +console.log(runs[0].workflowRunId); // first restarted run ID +console.log(runs[1].workflowRunId); // second restarted run ID +``` +```ts With Filters +const runs = await client.dlq.restart({ + label: "my-workflow-label", + workflowUrl: "https://your-endpoint.com/workflow", +}); + +console.log(`Restarted ${runs.length} workflow runs`); ``` diff --git a/workflow/basics/client/dlq/resume.mdx b/workflow/basics/client/dlq/resume.mdx index 88b88792..f1f3a46f 100644 --- a/workflow/basics/client/dlq/resume.mdx +++ b/workflow/basics/client/dlq/resume.mdx @@ -5,8 +5,12 @@ title: "client.dlq.resume" The `dlq.resume` method resumes one or more workflow runs from the **Dead Letter Queue (DLQ)** at the point where they previously failed. This allows you to continue execution from the failed step instead of restarting the workflow from the beginning. +Can be called with DLQ IDs (with optional `flowControl` and `retries`), or with a filter object to resume matching entries. + ## Arguments +### DLQ ID mode + The DLQ entry ID or list of IDs to resume. Use the `dlqId` field from messages returned by `client.dlq.list()`. @@ -42,20 +46,41 @@ This allows you to continue execution from the failed step instead of restarting Defaults to `3` if not provided. +### Filter mode + + + Resume DLQ entries with this label. + + + + Resume DLQ entries matching this workflow URL. + + + + Resume DLQ entries matching these workflow run IDs. + + + + Resume DLQ entries created after this date (Unix ms as string). + + + + Resume DLQ entries created before this date (Unix ms as string). + + ## Response -`client.dlq.resume()` returns one or more objects with details of the resumed workflow run(s): +The return type depends on the input: +- **Single DLQ ID (string)**: Returns a single object +- **Array of DLQ IDs**: Returns an array of objects +- **Filter mode**: Returns an array of objects - - - - The ID of the workflow run resumed from the DLQ message. - + + The ID of the workflow run resumed from the DLQ message. + - - The Unix timestamp (in milliseconds) when the resumed run was created. - - + + The timestamp when the resumed run was created. ## Usage @@ -64,20 +89,32 @@ This allows you to continue execution from the failed step instead of restarting ```ts Single const { messages } = await client.dlq.list(); -const response = await client.dlq.resume({ - dlqId: messages[0].dlqId, // Use the dlqId from the message +const run = await client.dlq.resume({ + dlqId: messages[0].dlqId, flowControl: { key: "my-flow-control-key", - value: "my-flow-control-value", + parallelism: 10, }, retries: 3, }); +console.log(run.workflowRunId); // ID of the resumed workflow run ``` ```ts Multiple -const responses = await client.dlq.resume({ +const runs = await client.dlq.resume({ dlqId: ["dlq-12345", "dlq-67890"], retries: 5, }); + +console.log(runs[0].workflowRunId); // first resumed run ID +console.log(runs[1].workflowRunId); // second resumed run ID +``` +```ts With Filters +const runs = await client.dlq.resume({ + label: "my-workflow-label", + workflowUrl: "https://your-endpoint.com/workflow", +}); + +console.log(`Resumed ${runs.length} workflow runs`); ``` diff --git a/workflow/features/dlq.mdx b/workflow/features/dlq.mdx index b43eb496..83739445 100644 --- a/workflow/features/dlq.mdx +++ b/workflow/features/dlq.mdx @@ -23,7 +23,8 @@ The DLQ serves as a safety net, preserving failed workflow runs with their compl - **Pay-as-you-go**: 1 week - **Fixed pricing**: Up to 3 months - After the retention duration expires, DLQ items are automatically removed and cannot be recovered. +After the retention duration expires, DLQ items are automatically removed and cannot be recovered. + ## Recovery Actions @@ -35,4 +36,44 @@ Once a workflow run is in the DLQ, you can take the following actions: - **[Re-run Failure Function](/workflow/features/dlq/callback)** – execute the workflow's failure handling logic again. - or delete the DLQ entry if no action is required. -You can apply these actions in bulk to multiple DLQ entries. Check the individual action pages for more details. \ No newline at end of file +You can apply these actions in bulk to multiple DLQ entries. Check the individual action pages for more details. + +## Listing DLQ entries + +```typescript +import { Client } from "@upstash/workflow"; + +const client = new Client({ token: "" }); + +// list all (paginated) +const { messages, cursor } = await client.dlq.list(); + +// filter by label or workflow URL +const { messages: filtered } = await client.dlq.list({ + filter: { label: "my-label" }, +}); + +// paginate with cursor +const { messages: page2 } = await client.dlq.list({ cursor, count: 50 }); +``` + +## Deleting DLQ entries + +```typescript +import { Client } from "@upstash/workflow"; + +const client = new Client({ token: "" }); + +// delete a single entry +await client.dlq.delete("dlqId"); + +// delete multiple entries by DLQ ID +await client.dlq.delete(["dlqId-1", "dlqId-2"]); + +// delete by label or workflow URL +await client.dlq.delete({ label: "my-label" }); +await client.dlq.delete({ workflowUrl: "https://my-app.com/api/workflow" }); + +// delete all entries +await client.dlq.delete({ all: true }); +``` diff --git a/workflow/features/dlq/restart.mdx b/workflow/features/dlq/restart.mdx index f9ac4441..52a6d40c 100644 --- a/workflow/features/dlq/restart.mdx +++ b/workflow/features/dlq/restart.mdx @@ -18,16 +18,41 @@ This approach is ideal when: You can perform this action programmatically as well: - ```typescript TypeScript + ```typescript Single run import { Client } from "@upstash/workflow"; const client = new Client({ token: "" }); - await client.dlq.restart({ + const run = await client.dlq.restart({ dlqId: "dlq-12345", retries: 3, }); + + console.log(`Restarted workflow run: ${run.workflowRunId}`); + ``` + + ```typescript Multiple runs + import { Client } from "@upstash/workflow"; + + const client = new Client({ token: "" }); + + const runs = await client.dlq.restart({ + dlqId: ["dlq-12345", "dlq-67890"], + }); + + runs.forEach((run) => console.log(run.workflowRunId)); ``` - + ```typescript Filter-based + import { Client } from "@upstash/workflow"; + const client = new Client({ token: "" }); + + const runs = await client.dlq.restart({ + workflowUrl: "https://my-app.com/api/workflow", + }); + + runs.forEach((run) => console.log(run.workflowRunId)); + ``` + + diff --git a/workflow/features/dlq/resume.mdx b/workflow/features/dlq/resume.mdx index 6fd669d1..44bc8284 100644 --- a/workflow/features/dlq/resume.mdx +++ b/workflow/features/dlq/resume.mdx @@ -17,16 +17,43 @@ This approach is ideal when: You can perform this action programmatically as well: - ```typescript TypeScript + ```typescript Single run import { Client } from "@upstash/workflow"; const client = new Client({ token: "" }); - await client.dlq.resume({ + const run = await client.dlq.resume({ dlqId: "dlq-12345", retries: 3, }); + + console.log(`Resumed workflow run: ${run.workflowRunId}`); + ``` + + ```typescript Multiple runs + import { Client } from "@upstash/workflow"; + + const client = new Client({ token: "" }); + + const runs = await client.dlq.resume({ + dlqId: ["dlq-12345", "dlq-67890"], + }); + + runs.forEach((run) => console.log(run.workflowRunId)); ``` + + ```typescript Filter-based + import { Client } from "@upstash/workflow"; + + const client = new Client({ token: "" }); + + const runs = await client.dlq.resume({ + workflowUrl: "https://my-app.com/api/workflow", + }); + + runs.forEach((run) => console.log(run.workflowRunId)); + ``` + @@ -34,4 +61,5 @@ You can perform this action programmatically as well: Changes to steps prior to the failure are not allowed and may break the workflow. For more details, check out the [Handle workflow route code changes](/workflow/howto/changes) page. + diff --git a/workflow/howto/cancel.mdx b/workflow/howto/cancel.mdx index ed62ec70..6d97f044 100644 --- a/workflow/howto/cancel.mdx +++ b/workflow/howto/cancel.mdx @@ -25,7 +25,8 @@ In your Upstash Workflow console, find the run you'd like to cancel and press th import { Client } from "@upstash/workflow"; const client = new Client({ token: "" }); -await client.cancel({ ids: "" }); +const result = await client.cancel({ ids: "" }); +console.log(`Cancelled ${result.cancelled} workflow(s)`); ``` And replace `` with your actual run ID. See [the documentation of `client.cancel` method for more information about other ways of canceling workflows](/workflow/basics/client/cancel). diff --git a/workflow/rest/runs/bulk-cancel.mdx b/workflow/rest/runs/bulk-cancel.mdx index b509de21..99a5e774 100644 --- a/workflow/rest/runs/bulk-cancel.mdx +++ b/workflow/rest/runs/bulk-cancel.mdx @@ -27,7 +27,16 @@ In such cases, you can run the bulk cancel operation multiple times. The list of workflow run IDs to cancel. - The prefix filter to match workflow run URLs. Workflow runs with URLs starting with this prefix will be canceled. + The workflow URL to filter. Can be used either for exact matches or as a prefix filter depending on the endpoint behavior. + + + Cancel workflows with this label. + + + Cancel workflows created after this date (Unix timestamp in milliseconds). + + + Cancel workflows created before this date (Unix timestamp in milliseconds). ## Response @@ -44,10 +53,27 @@ A cancelled object with the number of cancelled workflow runs. ```sh curl +# Cancel by workflow URL curl -XDELETE https://qstash.upstash.io/v2/workflows/runs \ - -H "Content-Type: application/json" \ + -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{"workflowUrl": "https://example.com"}' + +# Cancel with filters +curl -XDELETE https://qstash.upstash.io/v2/workflows/runs \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "label": "my-workflow-label", + "fromDate": 1640995200000, + "toDate": 1672531200000 + }' + +# Cancel all workflows (empty body) +curl -XDELETE https://qstash.upstash.io/v2/workflows/runs \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{}' ``` @@ -55,16 +81,32 @@ curl -XDELETE https://qstash.upstash.io/v2/workflows/runs \ import { Client } from "@upstash/workflow"; // cancel a set of workflow runs -await client.cancel({ ids: [ - "", - "", -]}) +const result = await client.cancel({ + ids: [ + "", + "", + ] +}); +console.log(`Cancelled ${result.cancelled} workflow(s)`); // cancel workflows starting with a url -await client.cancel({ urlStartingWith: "https://your-endpoint.com" }) +const result = await client.cancel({ + urlStartingWith: "https://your-endpoint.com" +}); + +// cancel workflows with a specific label +const result = await client.cancel({ + label: "my-workflow-label" +}); + +// cancel workflows within a date range +const result = await client.cancel({ + fromDate: "1640995200000", + toDate: "1672531200000", +}); -// cancel all workflows -await client.cancel({ all: true }) +// cancel all workflows (no parameters) +const result = await client.cancel({}); ``` diff --git a/workflow/rest/runs/cancel.mdx b/workflow/rest/runs/cancel.mdx index a235444d..7251af40 100644 --- a/workflow/rest/runs/cancel.mdx +++ b/workflow/rest/runs/cancel.mdx @@ -32,7 +32,8 @@ curl -XDELETE https://qstash.upstash.io/v2/workflows/runs/wfr_TzazoUCuZmFGp2u9cd import { Client } from "@upstash/workflow"; const client = new Client({ token: "" }) -await client.cancel({ workflowRunId: "" }) +const result = await client.cancel({ ids: "" }) +console.log(`Cancelled ${result.cancelled} workflow(s)`); ``` ```js Node