Skip to content

Commit b977842

Browse files
CahidArdaytkimirti
andauthored
DX-2238: document bulk actions (#654)
* DX-2238: document bulk actions * Update docs for new bulk action APIs Update QStash and Workflow SDK docs to reflect new filter-based bulk action APIs. Add cursor pagination to all bulk operations (delete, retry, cancel, resume, restart). Update Workflow docs for new API signatures where filters move into a filter object, dlqId becomes a direct argument, and new filter fields (callerIp, flowControlKey, etc.) are documented. --------- Co-authored-by: ytkimirti <yusuftaha9@gmail.com>
1 parent 780029f commit b977842

13 files changed

Lines changed: 689 additions & 113 deletions

File tree

docs.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,7 @@
13081308
"workflow/basics/client/dlq/list",
13091309
"workflow/basics/client/dlq/restart",
13101310
"workflow/basics/client/dlq/resume",
1311+
"workflow/basics/client/dlq/delete",
13111312
"workflow/basics/client/dlq/callback"
13121313
]
13131314
},
@@ -1345,6 +1346,7 @@
13451346
"workflow/features/dlq",
13461347
"workflow/features/dlq/restart",
13471348
"workflow/features/dlq/resume",
1349+
"workflow/features/dlq/delete",
13481350
"workflow/features/dlq/callback"
13491351
]
13501352
},

qstash/sdks/ts/examples/dlq.mdx

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ You can go through the results using the `cursor`.
1010
```typescript
1111
import { Client } from "@upstash/qstash";
1212

13-
const client = new Client("<QSTASH_TOKEN>");
14-
const dlq = client.dlq;
13+
const client = new Client({ token: "<QSTASH_TOKEN>" });
1514
const all_messages = [];
1615
let cursor = null;
1716
while (true) {
18-
const res = await dlq.listMessages({ cursor });
17+
const res = await client.dlq.listMessages({ cursor });
1918
all_messages.push(...res.messages);
2019
cursor = res.cursor;
2120
if (!cursor) {
@@ -24,12 +23,80 @@ while (true) {
2423
}
2524
```
2625

27-
#### Delete a message from the DLQ
26+
#### List messages with filters
2827

2928
```typescript
3029
import { Client } from "@upstash/qstash";
3130

3231
const client = new Client({ token: "<QSTASH_TOKEN>" });
33-
const dlq = client.dlq;
34-
await dlq.delete("dlqId");
32+
33+
// filter and paginate with top-level options
34+
const res = await client.dlq.listMessages({
35+
count: 10,
36+
order: "latestFirst",
37+
filter: { url: "https://example.com" }
38+
})
39+
40+
// fetch specific DLQ messages by ID
41+
const res2 = await client.dlq.listMessages({
42+
dlqIds: ["dlq-id-1", "dlq-id-2"]
43+
})
44+
```
45+
46+
#### Delete messages from the DLQ
47+
48+
```typescript
49+
import { Client } from "@upstash/qstash";
50+
51+
const client = new Client({ token: "<QSTASH_TOKEN>" });
52+
53+
// delete a single message
54+
await client.dlq.delete("dlqId");
55+
56+
// delete multiple messages
57+
await client.dlq.delete(["dlq-id-1", "dlq-id-2"]);
58+
59+
// delete with filters
60+
let cursor: string | undefined;
61+
do {
62+
const result = await client.dlq.delete({
63+
filter: { url: "https://example.com", responseStatus: 500 },
64+
cursor,
65+
});
66+
cursor = result.cursor;
67+
} while (cursor);
68+
69+
// delete all DLQ messages
70+
do {
71+
const result = await client.dlq.delete({ all: true, cursor });
72+
cursor = result.cursor;
73+
} while (cursor);
74+
```
75+
76+
<Note>
77+
`client.dlq.deleteMany()` is deprecated. Use `client.dlq.delete()` with an array of dlqIds or filters instead.
78+
</Note>
79+
80+
#### Retry messages from the DLQ
81+
82+
```typescript
83+
import { Client } from "@upstash/qstash";
84+
85+
const client = new Client({ token: "<QSTASH_TOKEN>" });
86+
87+
// retry a single message
88+
await client.dlq.retry("dlqId");
89+
90+
// retry multiple messages
91+
await client.dlq.retry(["dlq-id-1", "dlq-id-2"]);
92+
93+
// retry with filters
94+
let cursor: string | undefined;
95+
do {
96+
const result = await client.dlq.retry({
97+
filter: { queueName: "my-queue" },
98+
cursor,
99+
});
100+
cursor = result.cursor;
101+
} while (cursor);
35102
```

qstash/sdks/ts/examples/logs.mdx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ while (true) {
2323
}
2424
```
2525

26-
#### Filter logs by state and only return the first 50.
26+
#### Filter logs by state and limit results
2727

2828
<Info>
2929
More filters can be found in the [API Reference](/qstash/api-reference/logs/list-logs).
@@ -33,10 +33,21 @@ More filters can be found in the [API Reference](/qstash/api-reference/logs/list
3333
import { Client } from "@upstash/qstash";
3434

3535
const client = new Client({ token: "<QSTASH_TOKEN>" });
36-
const res = await client.logs({
36+
const res = await client.logs({
37+
count: 50,
3738
filter: {
3839
state: "DELIVERED",
39-
count: 50
4040
}
4141
});
42+
```
43+
44+
#### Fetch logs by message IDs
45+
46+
```typescript
47+
import { Client } from "@upstash/qstash";
48+
49+
const client = new Client({ token: "<QSTASH_TOKEN>" });
50+
const res = await client.logs({
51+
messageIds: ["msg-id-1", "msg-id-2"]
52+
});
4253
```

qstash/sdks/ts/examples/messages.mdx

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,55 @@ const messages = client.messages
1616
const msg = await messages.get("msgId");
1717
```
1818

19-
#### Cancel/delete a message
19+
#### Cancel a message
2020

2121
```typescript
2222
import { Client } from "@upstash/qstash";
2323

2424
const client = new Client({ token: "<QSTASH_TOKEN>" });
25-
const messages = client.messages
26-
const msg = await messages.delete("msgId");
25+
await client.messages.cancel("msgId");
2726
```
2827

29-
#### Cancel messages in bulk
30-
31-
Cancel many messages at once or cancel all messages
28+
#### Cancel multiple messages
3229

3330
```typescript
3431
import { Client } from "@upstash/qstash";
3532

3633
const client = new Client({ token: "<QSTASH_TOKEN>" });
3734

38-
// deleting two messages at once
39-
await client.messages.deleteMany([
40-
"message-id-1",
41-
"message-id-2",
42-
])
35+
// cancel two messages at once
36+
await client.messages.cancel(["message-id-1", "message-id-2"])
37+
38+
// cancel all messages
39+
let cancelled: number;
40+
do {
41+
const result = await client.messages.cancel({ all: true });
42+
cancelled = result.cancelled;
43+
} while (cancelled > 0);
44+
```
4345

46+
#### Cancel messages with filters
47+
48+
```typescript
49+
import { Client } from "@upstash/qstash";
50+
51+
const client = new Client({ token: "<QSTASH_TOKEN>" });
52+
53+
// cancel messages matching a URL and label
54+
let cancelled: number;
55+
do {
56+
const result = await client.messages.cancel({
57+
filter: {
58+
url: "https://example.com",
59+
label: "my-label",
60+
}
61+
});
62+
cancelled = result.cancelled;
63+
} while (cancelled > 0);
4464

45-
// deleting all messages
46-
await client.messages.deleteAll()
4765
```
66+
67+
<Note>
68+
`client.messages.delete()`, `client.messages.deleteMany()`, and `client.messages.deleteAll()`
69+
are deprecated. Use `client.messages.cancel()` instead.
70+
</Note>

workflow/basics/client.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ The client exposes a set of functions to manage workflow runs and inspect their
3535
- [client.dlq.list](/workflow/basics/client/dlq/list)
3636
- [client.dlq.restart](/workflow/basics/client/dlq/restart)
3737
- [client.dlq.resume](/workflow/basics/client/dlq/resume)
38+
- [client.dlq.delete](/workflow/basics/client/dlq/delete)
3839
- [client.dlq.retryFailureFunction](/workflow/basics/client/dlq/callback)

workflow/basics/client/cancel.mdx

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,55 +2,135 @@
22
title: "client.cancel"
33
---
44

5-
There are multiple ways you can cancel workflow runs:
6-
7-
- Pass one or more workflow run ids to cancel them
8-
- Pass a workflow url to cancel all runs starting with this url
9-
- cancel all pending or active workflow runs
5+
Cancel one or more workflow runs. You can pass IDs directly, use filters, or cancel all at once.
106

117
## Arguments
128

13-
<ParamField body="ids" type="array">
14-
The set of workflow run IDs you want to cancel
9+
The `cancel` method accepts one of the following:
10+
11+
### By ID
12+
13+
Pass a single workflow run ID or an array of IDs directly:
14+
15+
```ts
16+
await client.cancel("<WORKFLOW_RUN_ID>");
17+
await client.cancel(["<ID_1>", "<ID_2>"]);
18+
```
19+
20+
### By filters
21+
22+
Pass an object with a `filter` field containing one or more filter criteria:
23+
24+
<ParamField body="filter" type="object">
25+
<Expandable defaultOpen>
26+
<ParamField body="workflowUrl" type="string" optional>
27+
Cancel workflows matching this exact URL. Cannot be combined with `workflowUrlStartingWith`.
28+
</ParamField>
29+
30+
<ParamField body="workflowUrlStartingWith" type="string" optional>
31+
Cancel workflows whose URL starts with this prefix. Cannot be combined with `workflowUrl`.
32+
</ParamField>
33+
34+
<ParamField body="label" type="string" optional>
35+
Cancel workflows with this label.
36+
</ParamField>
37+
38+
<ParamField body="fromDate" type="Date | number" optional>
39+
Cancel workflows created after this date. Accepts `Date` objects or Unix timestamps (ms).
40+
</ParamField>
41+
42+
<ParamField body="toDate" type="Date | number" optional>
43+
Cancel workflows created before this date. Accepts `Date` objects or Unix timestamps (ms).
44+
</ParamField>
45+
46+
<ParamField body="callerIp" type="string" optional>
47+
Cancel workflows triggered by this IP address.
48+
</ParamField>
49+
50+
<ParamField body="flowControlKey" type="string" optional>
51+
Cancel workflows with this flow control key.
52+
</ParamField>
53+
</Expandable>
1554
</ParamField>
1655

17-
<ParamField body="urlStartingWith" type="string">
18-
The URL address you want to filter while canceling
56+
<ParamField body="count" type="number" optional>
57+
Maximum number of workflow runs to cancel per call. Defaults to `100`.
1958
</ParamField>
2059

21-
<ParamField body="all" type="bool">
22-
Whether you want to cancel all workflow runs without any filter.
60+
### Cancel all
61+
62+
<ParamField body="all" type="boolean">
63+
Set to `true` to cancel all pending and active workflow runs.
2364
</ParamField>
2465

66+
## Response
67+
68+
<ResponseField name="cancelled" type="number">
69+
The number of workflow runs that were cancelled.
70+
</ResponseField>
71+
2572
## Usage
2673

27-
### Cancel a set of workflow runs
74+
### Cancel by ID
2875

2976
```ts
3077
// cancel a single workflow
31-
await client.cancel({ ids: "<WORKFLOW_RUN_ID>" });
78+
await client.cancel("<WORKFLOW_RUN_ID>");
3279

3380
// cancel a set of workflow runs
34-
await client.cancel({ ids: ["<WORKFLOW_RUN_ID_1>", "<WORKFLOW_RUN_ID_2>"] });
81+
await client.cancel(["<WORKFLOW_RUN_ID_1>", "<WORKFLOW_RUN_ID_2>"]);
3582
```
3683

37-
### Cancel workflow runs with URL filter
84+
### Cancel with URL filter
3885

39-
If you have an endpoint called `https://your-endpoint.com` and you
40-
want to cancel all workflow runs on it, you can use `urlStartingWith`.
86+
Cancel all workflow runs on a specific endpoint using a URL prefix:
87+
88+
```ts
89+
await client.cancel({
90+
filter: { workflowUrlStartingWith: "https://your-endpoint.com" }
91+
});
92+
```
4193

42-
Note that this will cancel workflows in all endpoints under
43-
`https://your-endpoint.com`.
94+
For an exact URL match:
4495

4596
```ts
46-
await client.cancel({ urlStartingWith: "https://your-endpoint.com" });
97+
await client.cancel({
98+
filter: { workflowUrl: "https://your-endpoint.com/api/workflow" }
99+
});
47100
```
48101

49-
### Cancel _all_ workflows
102+
### Cancel with filters
103+
104+
You can combine multiple filter parameters:
105+
106+
```ts
107+
// cancel by label
108+
await client.cancel({ filter: { label: "my-label" } });
109+
110+
// cancel by label and date range
111+
await client.cancel({
112+
filter: {
113+
label: "my-label",
114+
fromDate: 1640995200000,
115+
}
116+
});
117+
118+
// cancel by URL and date range
119+
await client.cancel({
120+
filter: {
121+
workflowUrl: "https://your-endpoint.com/api/workflow",
122+
fromDate: new Date("2024-01-01"),
123+
toDate: new Date("2024-06-01"),
124+
}
125+
});
126+
```
50127

51-
To cancel all pending and currently running workflows, you can
52-
do it like this:
128+
### Cancel _all_ workflows
53129

54130
```ts
55-
await client.cancel({ all: true });
131+
let cancelled: number;
132+
do {
133+
const result = await client.cancel({ all: true });
134+
cancelled = result.cancelled;
135+
} while (cancelled > 0);
56136
```

0 commit comments

Comments
 (0)