@trigger.dev/sdk 4.7.3 → 4.8.0-webhooks.20261015065339
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonjs/v3/ai.d.ts +560 -8
- package/dist/commonjs/v3/ai.js +2263 -178
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/chat.d.ts +23 -0
- package/dist/commonjs/v3/chat.js.map +1 -1
- package/dist/commonjs/v3/concurrencyLimits.d.ts +37 -7
- package/dist/commonjs/v3/concurrencyLimits.js +38 -70
- package/dist/commonjs/v3/concurrencyLimits.js.map +1 -1
- package/dist/commonjs/v3/index.d.ts +3 -1
- package/dist/commonjs/v3/index.js +23 -17
- package/dist/commonjs/v3/index.js.map +1 -1
- package/dist/commonjs/v3/modelFileDownload.d.ts +10 -0
- package/dist/commonjs/v3/modelFileDownload.js +164 -0
- package/dist/commonjs/v3/modelFileDownload.js.map +1 -0
- package/dist/commonjs/v3/runs.d.ts +22 -1
- package/dist/commonjs/v3/runs.js +6 -3
- package/dist/commonjs/v3/runs.js.map +1 -1
- package/dist/commonjs/v3/test/index.d.ts +2 -1
- package/dist/commonjs/v3/test/index.js +4 -1
- package/dist/commonjs/v3/test/index.js.map +1 -1
- package/dist/commonjs/v3/test/mock-channel-connector.d.ts +172 -0
- package/dist/commonjs/v3/test/mock-channel-connector.js +173 -0
- package/dist/commonjs/v3/test/mock-channel-connector.js.map +1 -0
- package/dist/commonjs/v3/test/mock-chat-agent.d.ts +81 -1
- package/dist/commonjs/v3/test/mock-chat-agent.js +137 -10
- package/dist/commonjs/v3/test/mock-chat-agent.js.map +1 -1
- package/dist/commonjs/v3/transcriptStorage.d.ts +44 -1
- package/dist/commonjs/v3/transcriptStorage.js +24 -0
- package/dist/commonjs/v3/transcriptStorage.js.map +1 -1
- package/dist/commonjs/v3/webhookWaiters.d.ts +80 -0
- package/dist/commonjs/v3/webhookWaiters.js +156 -0
- package/dist/commonjs/v3/webhookWaiters.js.map +1 -0
- package/dist/commonjs/v3/webhooks.d.ts +178 -2
- package/dist/commonjs/v3/webhooks.js +322 -1
- package/dist/commonjs/v3/webhooks.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/v3/ai.d.ts +560 -8
- package/dist/esm/v3/ai.js +2257 -178
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/chat.d.ts +23 -0
- package/dist/esm/v3/chat.js.map +1 -1
- package/dist/esm/v3/concurrencyLimits.d.ts +37 -7
- package/dist/esm/v3/concurrencyLimits.js +38 -70
- package/dist/esm/v3/concurrencyLimits.js.map +1 -1
- package/dist/esm/v3/index.d.ts +3 -1
- package/dist/esm/v3/index.js +1 -0
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/esm/v3/modelFileDownload.d.ts +10 -0
- package/dist/esm/v3/modelFileDownload.js +161 -0
- package/dist/esm/v3/modelFileDownload.js.map +1 -0
- package/dist/esm/v3/runs.d.ts +22 -1
- package/dist/esm/v3/runs.js +6 -3
- package/dist/esm/v3/runs.js.map +1 -1
- package/dist/esm/v3/test/index.d.ts +2 -1
- package/dist/esm/v3/test/index.js +2 -1
- package/dist/esm/v3/test/index.js.map +1 -1
- package/dist/esm/v3/test/mock-channel-connector.d.ts +172 -0
- package/dist/esm/v3/test/mock-channel-connector.js +170 -0
- package/dist/esm/v3/test/mock-channel-connector.js.map +1 -0
- package/dist/esm/v3/test/mock-chat-agent.d.ts +81 -1
- package/dist/esm/v3/test/mock-chat-agent.js +137 -11
- package/dist/esm/v3/test/mock-chat-agent.js.map +1 -1
- package/dist/esm/v3/transcriptStorage.d.ts +44 -1
- package/dist/esm/v3/transcriptStorage.js +24 -0
- package/dist/esm/v3/transcriptStorage.js.map +1 -1
- package/dist/esm/v3/webhookWaiters.d.ts +80 -0
- package/dist/esm/v3/webhookWaiters.js +149 -0
- package/dist/esm/v3/webhookWaiters.js.map +1 -0
- package/dist/esm/v3/webhooks.d.ts +178 -2
- package/dist/esm/v3/webhooks.js +318 -1
- package/dist/esm/v3/webhooks.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/ai-chat/actions.mdx +6 -1
- package/docs/ai-chat/backend.mdx +34 -0
- package/docs/ai-chat/patterns/sub-agents.mdx +33 -0
- package/docs/ai-chat/pending-messages.mdx +2 -0
- package/docs/ai-chat/reference.mdx +50 -2
- package/docs/apikeys.mdx +3 -3
- package/docs/billing-limits.mdx +1 -1
- package/docs/cli-env-commands.mdx +5 -4
- package/docs/cli-init-commands.mdx +27 -1
- package/docs/cli-login-commands.mdx +20 -0
- package/docs/cli-projects-commands.mdx +13 -1
- package/docs/cli-runs-commands.mdx +3 -2
- package/docs/cli-update-commands.mdx +9 -3
- package/docs/cli-whoami-commands.mdx +12 -0
- package/docs/concurrency.mdx +32 -0
- package/docs/config/extensions/audioWaveform.mdx +4 -1
- package/docs/config/extensions/overview.mdx +2 -0
- package/docs/config/extensions/prismaExtension.mdx +2 -3
- package/docs/config/extensions/puppeteer.mdx +3 -5
- package/docs/config/extensions/pythonExtension.mdx +9 -1
- package/docs/config/extensions/syncEnvVars.mdx +6 -0
- package/docs/deploy-environment-variables.mdx +1 -1
- package/docs/deployment/atomic-deployment.mdx +2 -0
- package/docs/deployment/dev-branches.mdx +5 -5
- package/docs/deployment/overview.mdx +8 -7
- package/docs/deployment/preview-branches.mdx +6 -3
- package/docs/errors-retrying.mdx +4 -4
- package/docs/how-it-works.mdx +5 -5
- package/docs/introduction.mdx +6 -0
- package/docs/limits.mdx +26 -8
- package/docs/logging.mdx +1 -1
- package/docs/machines.mdx +1 -1
- package/docs/mcp-introduction.mdx +8 -7
- package/docs/mcp-tools.mdx +91 -1
- package/docs/migrating-from-v3.mdx +1 -1
- package/docs/observability/dashboards.mdx +2 -0
- package/docs/observability/query.mdx +6 -2
- package/docs/private-networking/aws-console-setup.mdx +1 -1
- package/docs/private-networking/overview.mdx +1 -1
- package/docs/quick-start.mdx +3 -40
- package/docs/realtime/auth.mdx +1 -1
- package/docs/realtime/backend/input-streams.mdx +159 -0
- package/docs/realtime/backend/streams.mdx +25 -10
- package/docs/realtime/how-it-works.mdx +1 -1
- package/docs/realtime/react-hooks/overview.mdx +1 -1
- package/docs/realtime/react-hooks/streams.mdx +2 -2
- package/docs/realtime/react-hooks/subscribe.mdx +19 -3
- package/docs/realtime/react-hooks/triggering.mdx +2 -2
- package/docs/realtime/react-hooks/use-wait-token.mdx +1 -1
- package/docs/realtime/run-object.mdx +47 -24
- package/docs/replaying.mdx +26 -1
- package/docs/reports.mdx +4 -2
- package/docs/run-tests.mdx +2 -2
- package/docs/run-usage.mdx +3 -3
- package/docs/runs/heartbeats.mdx +2 -2
- package/docs/runs/list-best-practices.mdx +234 -0
- package/docs/runs/metadata.mdx +7 -10
- package/docs/runs.mdx +18 -8
- package/docs/self-hosting/env/supervisor.mdx +2 -0
- package/docs/self-hosting/env/webapp.mdx +5 -0
- package/docs/self-hosting/overview.mdx +26 -0
- package/docs/tags.mdx +6 -0
- package/docs/tasks/scheduled.mdx +11 -5
- package/docs/triggering.mdx +8 -0
- package/docs/troubleshooting-alerts.mdx +102 -3
- package/docs/troubleshooting.mdx +1 -1
- package/docs/upgrading-packages.mdx +3 -3
- package/docs/vercel-integration.mdx +13 -3
- package/docs/versioning.mdx +1 -1
- package/docs/wait-for-token.mdx +3 -3
- package/docs/webhooks/channels.mdx +128 -0
- package/docs/webhooks/connect.mdx +80 -0
- package/docs/webhooks/deliveries.mdx +92 -0
- package/docs/webhooks/filters.mdx +109 -0
- package/docs/webhooks/human-in-the-loop.mdx +149 -0
- package/docs/webhooks/linear.mdx +185 -0
- package/docs/webhooks/overview.mdx +99 -0
- package/docs/webhooks/session-routing.mdx +132 -0
- package/docs/webhooks/slack.mdx +360 -0
- package/docs/webhooks/sources.mdx +217 -0
- package/docs/webhooks/waiters.mdx +170 -0
- package/package.json +3 -2
|
@@ -119,6 +119,15 @@ export function RunStatusBadge({
|
|
|
119
119
|
|
|
120
120
|
You can skip any of: `payload`, `output`, `metadata`, `startedAt`, `delayUntil`, `queuedAt`, `expiredAt`, `completedAt`, `number`, `isTest`, `usageDurationMs`, `costInCents`, `baseCostInCents`, `ttl`, `payloadType`, `outputType`, `runTags`, `error`. The `useRealtimeRunsWithTag` hook also accepts a `skipColumns` option in the same way.
|
|
121
121
|
|
|
122
|
+
By default the hook stops subscribing once the run completes. Pass `stopOnCompletion: false` to keep receiving updates after completion, for example metadata updates from child runs.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
const { run, error } = useRealtimeRun(runId, {
|
|
126
|
+
accessToken: publicAccessToken,
|
|
127
|
+
stopOnCompletion: false, // Keep receiving updates after the run completes
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
122
131
|
See our [run object reference](/realtime/run-object) for the complete schema and [How it Works documentation](/realtime/how-it-works) for more technical details.
|
|
123
132
|
|
|
124
133
|
### useRealtimeRunsWithTag
|
|
@@ -198,6 +207,14 @@ export function MyComponent({ tag }: { tag: string }) {
|
|
|
198
207
|
}
|
|
199
208
|
```
|
|
200
209
|
|
|
210
|
+
You can also pass an array of tags, and use the `createdAt` option to only subscribe to runs created within a recent period. It accepts a duration string such as `"30m"` or `"1h"` and is applied when the subscription starts. The default and maximum lookback is 24 hours, so longer durations are capped at 24 hours.
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
const { runs, error } = useRealtimeRunsWithTag(["user:123", "report"], {
|
|
214
|
+
createdAt: "1h", // Only runs created in the last hour
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
201
218
|
### useRealtimeBatch
|
|
202
219
|
|
|
203
220
|
The `useRealtimeBatch` hook allows you to subscribe to a batch of runs by its the batch ID.
|
|
@@ -246,13 +263,12 @@ export function ProgressMonitor({
|
|
|
246
263
|
runId: string;
|
|
247
264
|
publicAccessToken: string;
|
|
248
265
|
}) {
|
|
249
|
-
const { run, error
|
|
266
|
+
const { run, error } = useRealtimeRun(runId, {
|
|
250
267
|
accessToken: publicAccessToken,
|
|
251
268
|
});
|
|
252
269
|
|
|
253
|
-
if (isLoading) return <div>Loading run...</div>;
|
|
254
270
|
if (error) return <div>Error: {error.message}</div>;
|
|
255
|
-
if (!run) return <div>
|
|
271
|
+
if (!run) return <div>Loading run...</div>;
|
|
256
272
|
|
|
257
273
|
const progress = run.metadata?.progress as
|
|
258
274
|
| {
|
|
@@ -84,8 +84,8 @@ export function MyComponent({ publicAccessToken }: { publicAccessToken: string }
|
|
|
84
84
|
accessToken: publicAccessToken, // 👈 this is the "trigger" token
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
//
|
|
88
|
-
const { run, error: realtimeError } = useRealtimeRun(handle, {
|
|
87
|
+
// pass the run ID and the task type to preserve type-safety 👇
|
|
88
|
+
const { run, error: realtimeError } = useRealtimeRun<typeof myTask>(handle?.id, {
|
|
89
89
|
accessToken: handle?.publicAccessToken,
|
|
90
90
|
enabled: !!handle, // Only subscribe to the run if the handle is available
|
|
91
91
|
});
|
|
@@ -15,7 +15,7 @@ const token = await wait.createToken({
|
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
tokenId: token.id,
|
|
18
|
-
publicToken: token.publicAccessToken, // An automatically generated public access token that expires in
|
|
18
|
+
publicToken: token.publicAccessToken, // An automatically generated public access token that expires in 24 hours
|
|
19
19
|
};
|
|
20
20
|
```
|
|
21
21
|
|
|
@@ -36,31 +36,26 @@ Type-safety is supported for the run object, so you can infer the types of the r
|
|
|
36
36
|
Timestamp when the run was last updated.
|
|
37
37
|
</ParamField>
|
|
38
38
|
|
|
39
|
-
<ParamField path="number" type="number" required>
|
|
40
|
-
Sequential number assigned to the run.
|
|
41
|
-
</ParamField>
|
|
42
|
-
|
|
43
39
|
<ParamField path="status" type="RunStatus" required>
|
|
44
40
|
Current status of the run.
|
|
45
41
|
|
|
46
42
|
<Accordion title="RunStatus enum">
|
|
47
43
|
|
|
48
|
-
| Status
|
|
49
|
-
|
|
|
50
|
-
| `
|
|
51
|
-
| `QUEUED`
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `COMPLETED`
|
|
56
|
-
| `CANCELED`
|
|
57
|
-
| `FAILED`
|
|
58
|
-
| `CRASHED`
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `TIMED_OUT` | Run has reached it's maxDuration and has been stopped |
|
|
44
|
+
| Status | Description |
|
|
45
|
+
| ----------------- | --------------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| `PENDING_VERSION` | Run is waiting for a version update because it cannot execute without additional information |
|
|
47
|
+
| `QUEUED` | Run is waiting to be executed by a worker |
|
|
48
|
+
| `DEQUEUED` | Run has been dequeued and is being sent to a worker to start executing |
|
|
49
|
+
| `EXECUTING` | Run is currently being executed by a worker |
|
|
50
|
+
| `WAITING` | Run has been paused by the system, and will be resumed by the system |
|
|
51
|
+
| `COMPLETED` | Run has been completed successfully |
|
|
52
|
+
| `CANCELED` | Run has been canceled by the user |
|
|
53
|
+
| `FAILED` | Run has been completed with errors |
|
|
54
|
+
| `CRASHED` | Run has crashed and won't be retried, most likely the worker ran out of resources, e.g. memory or storage |
|
|
55
|
+
| `SYSTEM_FAILURE` | Run has failed to complete, due to an error in the system |
|
|
56
|
+
| `DELAYED` | Run has been scheduled to run at a specific time |
|
|
57
|
+
| `EXPIRED` | Run has expired and won't be executed |
|
|
58
|
+
| `TIMED_OUT` | Run has reached it's maxDuration and has been stopped |
|
|
64
59
|
|
|
65
60
|
</Accordion>
|
|
66
61
|
</ParamField>
|
|
@@ -89,10 +84,6 @@ Type-safety is supported for the run object, so you can infer the types of the r
|
|
|
89
84
|
Timestamp when the run expired.
|
|
90
85
|
</ParamField>
|
|
91
86
|
|
|
92
|
-
<ParamField path="ttl" type="string">
|
|
93
|
-
Time-to-live duration for the run.
|
|
94
|
-
</ParamField>
|
|
95
|
-
|
|
96
87
|
<ParamField path="finishedAt" type="Date">
|
|
97
88
|
Timestamp when the run finished.
|
|
98
89
|
</ParamField>
|
|
@@ -121,6 +112,38 @@ Type-safety is supported for the run object, so you can infer the types of the r
|
|
|
121
112
|
Indicates whether this is a test run.
|
|
122
113
|
</ParamField>
|
|
123
114
|
|
|
115
|
+
<ParamField path="realtimeStreams" type="string[]" required>
|
|
116
|
+
Names of the Realtime streams on the run.
|
|
117
|
+
</ParamField>
|
|
118
|
+
|
|
119
|
+
<ParamField path="isQueued" type="boolean" required>
|
|
120
|
+
`true` if the run is queued, delayed or waiting for a version update.
|
|
121
|
+
</ParamField>
|
|
122
|
+
|
|
123
|
+
<ParamField path="isExecuting" type="boolean" required>
|
|
124
|
+
`true` if the run is dequeued or executing.
|
|
125
|
+
</ParamField>
|
|
126
|
+
|
|
127
|
+
<ParamField path="isWaiting" type="boolean" required>
|
|
128
|
+
`true` if the run is waiting.
|
|
129
|
+
</ParamField>
|
|
130
|
+
|
|
131
|
+
<ParamField path="isCompleted" type="boolean" required>
|
|
132
|
+
`true` if the run has finished, either successfully or with any failure status.
|
|
133
|
+
</ParamField>
|
|
134
|
+
|
|
135
|
+
<ParamField path="isFailed" type="boolean" required>
|
|
136
|
+
`true` if the run failed, crashed, hit a system failure, expired or timed out.
|
|
137
|
+
</ParamField>
|
|
138
|
+
|
|
139
|
+
<ParamField path="isSuccess" type="boolean" required>
|
|
140
|
+
`true` if the run completed successfully.
|
|
141
|
+
</ParamField>
|
|
142
|
+
|
|
143
|
+
<ParamField path="isCancelled" type="boolean" required>
|
|
144
|
+
`true` if the run was canceled.
|
|
145
|
+
</ParamField>
|
|
146
|
+
|
|
124
147
|
## Type-safety
|
|
125
148
|
|
|
126
149
|
You can infer the types of the run's payload and output by passing the type of the task to the `subscribeToRun` function. This will give you type-safe access to the run's payload and output.
|
package/docs/replaying.mdx
CHANGED
|
@@ -49,10 +49,35 @@ export const myTask = task({
|
|
|
49
49
|
|
|
50
50
|
You can replay a run using the SDK:
|
|
51
51
|
|
|
52
|
-
```ts
|
|
52
|
+
```ts Your backend code
|
|
53
|
+
import { runs } from "@trigger.dev/sdk";
|
|
54
|
+
|
|
53
55
|
const replayedRun = await runs.replay(run.id);
|
|
56
|
+
// { id: "run_cmv6ixfn30008ct9kegazjolu" }
|
|
54
57
|
```
|
|
55
58
|
|
|
59
|
+
The new run reuses the original run's payload, metadata, tags, queue, concurrency key, and machine. Pass options to override any of them for the new run:
|
|
60
|
+
|
|
61
|
+
```ts Your backend code
|
|
62
|
+
import { runs } from "@trigger.dev/sdk";
|
|
63
|
+
|
|
64
|
+
const replayedRun = await runs.replay(run.id, {
|
|
65
|
+
payload: { userId: "user_456" },
|
|
66
|
+
metadata: { source: "replay" },
|
|
67
|
+
tags: ["replayed"],
|
|
68
|
+
machine: "large-1x",
|
|
69
|
+
delay: "10m",
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The options use the same names as [`trigger()` options](/triggering): `payload`, `metadata`, `tags`, `queue`, `concurrencyKey`, `machine`, `version`, `region`, `delay`, `ttl`, `idempotencyKey`, `idempotencyKeyTTL`, `maxAttempts`, `maxDuration`, and `priority`. If you leave out `payload`, `metadata`, `tags`, `queue`, `concurrencyKey`, or `machine`, the new run uses the original run's value. The other options fall back to the task's current defaults, and without `version` the replay runs on the current version. The replay always runs in the same environment as the original run.
|
|
74
|
+
|
|
75
|
+
A `queue` must already exist in the environment, and a `version` must be a version deployed to it. Otherwise the replay fails with an error and no run is created.
|
|
76
|
+
|
|
77
|
+
A replay starts a new run, so the API key or token you replay with needs permission to trigger the task as well as write access to the run.
|
|
78
|
+
|
|
79
|
+
The SDK serializes a `payload` override the same way `trigger()` does, so values like `Date`, `BigInt`, `Map` and `Set` reach the task with their types.
|
|
80
|
+
|
|
56
81
|
When you call `trigger()` or `batchTrigger()` on a task you receive back a run handle which has an `id` property. You can use that `id` to replay the run.
|
|
57
82
|
|
|
58
83
|
You can also access the run id from inside a run. You could write this to your database and then replay it later.
|
package/docs/reports.mdx
CHANGED
|
@@ -123,7 +123,7 @@ The MCP server also registers a `report` prompt, which hosts that support MCP pr
|
|
|
123
123
|
|
|
124
124
|
### HTTP API: `GET /api/v1/reports/:key`
|
|
125
125
|
|
|
126
|
-
The endpoint behind every surface. It accepts a `period` and a `format`, and authenticates with a
|
|
126
|
+
The endpoint behind every surface. It accepts a `period` and a `format`, and authenticates with an environment secret key or a JWT scoped to read the report's query tables (`read:query`).
|
|
127
127
|
|
|
128
128
|
| Query param | Default | Description |
|
|
129
129
|
| --- | --- | --- |
|
|
@@ -134,9 +134,11 @@ The endpoint behind every surface. It accepts a `period` and a `format`, and aut
|
|
|
134
134
|
|
|
135
135
|
```bash
|
|
136
136
|
curl "https://api.trigger.dev/api/v1/reports/health?period=24h&format=json" \
|
|
137
|
-
-H "Authorization: Bearer $
|
|
137
|
+
-H "Authorization: Bearer $TRIGGER_SECRET_KEY"
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
The environment comes from the key. Use an environment secret key, or a JWT scoped `read:query` for the report's tables. Personal access tokens are not accepted.
|
|
141
|
+
|
|
140
142
|
An unknown report key returns `404` with the list of available keys.
|
|
141
143
|
|
|
142
144
|
## Next steps
|
package/docs/run-tests.mdx
CHANGED
|
@@ -7,8 +7,8 @@ You can run a test for any of your tasks, in any environment, from the dashboard
|
|
|
7
7
|
|
|
8
8
|
<Note>
|
|
9
9
|
There is no longer a "Test" page in the sidebar. You test a task from the task itself: on the
|
|
10
|
-
Tasks page
|
|
11
|
-
"
|
|
10
|
+
Tasks page use the "Test" action next to a task, or open the task and press "Test task" ("Test
|
|
11
|
+
schedule" for a scheduled task), to open its test page.
|
|
12
12
|
</Note>
|
|
13
13
|
|
|
14
14
|
On a task's test page you can:
|
package/docs/run-usage.mdx
CHANGED
|
@@ -38,10 +38,10 @@ export const heavyTask = task({
|
|
|
38
38
|
}
|
|
39
39
|
*/
|
|
40
40
|
|
|
41
|
-
// In the cloud product we do not count waits towards the compute cost or duration.
|
|
41
|
+
// In the cloud product we do not count waits longer than 5 seconds towards the compute cost or duration.
|
|
42
42
|
// We also don't include time between attempts or before the run starts executing your code.
|
|
43
43
|
// So this line does not affect the cost or duration.
|
|
44
|
-
await wait.for({ seconds:
|
|
44
|
+
await wait.for({ seconds: 10 });
|
|
45
45
|
|
|
46
46
|
// This will give the same result as before the wait.
|
|
47
47
|
currentUsage = usage.getCurrent();
|
|
@@ -57,7 +57,7 @@ export const heavyTask = task({
|
|
|
57
57
|
|
|
58
58
|
<Note>
|
|
59
59
|
In Trigger.dev cloud we do not include time between attempts, before your code executes, or waits
|
|
60
|
-
towards the compute cost or duration.
|
|
60
|
+
longer than 5 seconds towards the compute cost or duration. Waits of 5 seconds or less still count.
|
|
61
61
|
</Note>
|
|
62
62
|
|
|
63
63
|
## Getting the run cost and duration from your backend
|
package/docs/runs/heartbeats.mdx
CHANGED
|
@@ -4,7 +4,7 @@ sidebarTitle: "Heartbeats"
|
|
|
4
4
|
description: "Keep long-running or CPU-heavy tasks from being marked as stalled."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
We send a heartbeat from your task to the platform every 30 seconds. If we don't receive a heartbeat within 5 minutes, we mark the run as stalled and stop it with a `TASK_RUN_STALLED_EXECUTING` error.
|
|
7
|
+
We send a heartbeat from your task to the platform every 20 seconds by default for deployed runs (30 seconds in local dev). If we don't receive a heartbeat within 5 minutes, we mark the run as stalled and stop it with a `TASK_RUN_STALLED_EXECUTING` error.
|
|
8
8
|
|
|
9
9
|
Code that blocks the event loop for too long (for example, a tight loop doing synchronous work on a large dataset) can prevent heartbeats from being sent. In that case, use `heartbeats.yield()` inside the loop so the runtime can yield to the event loop and send a heartbeat. You can call it every iteration; the implementation only yields when needed.
|
|
10
10
|
|
|
@@ -31,7 +31,7 @@ If you see `TASK_RUN_STALLED_EXECUTING`, see [Task run stalled executing](/troub
|
|
|
31
31
|
|
|
32
32
|
## Sending progress to Trigger.dev
|
|
33
33
|
|
|
34
|
-
To stream progress or status updates to the dashboard and your app, use [run metadata](/runs/metadata). Call `metadata.set()` (or `metadata.append()`) as the task runs. The dashboard and [Realtime](/realtime) (including `runs.subscribeToRun` and the React hooks) receive those updates as they happen. See [
|
|
34
|
+
To stream progress or status updates to the dashboard and your app, use [run metadata](/runs/metadata). Call `metadata.set()` (or `metadata.append()`) as the task runs. The dashboard and [Realtime](/realtime) (including `runs.subscribeToRun` and the React hooks) receive those updates as they happen. See [Subscribe to metadata updates](/realtime/backend/subscribe#subscribe-to-metadata-updates-from-your-tasks) for a full example.
|
|
35
35
|
|
|
36
36
|
## Sending updates to your own system
|
|
37
37
|
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Using runs.list() efficiently"
|
|
3
|
+
sidebarTitle: "runs.list() best practices"
|
|
4
|
+
description: "When to use runs.list(), the patterns to avoid, and what to use instead."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
`runs.list()` (and `GET /api/v1/runs`) is built for browsing, reporting, and bulk operations. It is not a coordination tool. Each call searches your environment's runs in the requested time window, so its cost depends on how many runs you created in that window much more than on the page size you ask for.
|
|
8
|
+
|
|
9
|
+
A call with `limit: 4` in a busy environment can still search millions of runs to find those 4. That's fine once in a while. On a hot path, like before every trigger or in a loop every second, it slows your own code down and counts against your [API rate limit](/limits).
|
|
10
|
+
|
|
11
|
+
## Quick reference
|
|
12
|
+
|
|
13
|
+
| You want to… | Avoid | Use instead |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Avoid piling up runs for the same work | `runs.list()` then `trigger()` | [`debounce`](/triggering#debounce) to merge a burst into one run, a [concurrency limit](/concurrency) so runs queue instead of overlapping, or an [`idempotencyKey`](/idempotency) for one run per item |
|
|
16
|
+
| Collapse a burst of triggers into one run | A fixed `delay` on every trigger | [`debounce`](/triggering#debounce) |
|
|
17
|
+
| Avoid duplicate runs for the same work | A random `idempotencyKey` per trigger | A key derived from the work itself |
|
|
18
|
+
| Wait for a run you triggered | Polling `runs.list()` or `runs.retrieve()` | [`triggerAndWait()`](/triggering#yourtask-triggerandwait) inside a task, or [`runs.subscribeToRun()`](/realtime/backend/subscribe) |
|
|
19
|
+
| Follow a group of runs | Polling `runs.list({ tag })` | [`runs.subscribeToRunsWithTag()`](/realtime/backend/subscribe) |
|
|
20
|
+
| Know how backed up a queue is | Counting `QUEUED` runs with `runs.list()` | [`queues.retrieve()`](/queues#retrieving-a-queue) |
|
|
21
|
+
|
|
22
|
+
## Anti-patterns
|
|
23
|
+
|
|
24
|
+
### Checking for active runs before triggering
|
|
25
|
+
|
|
26
|
+
This pattern tries to make sure only one run handles a piece of work at a time:
|
|
27
|
+
|
|
28
|
+
```ts Avoid
|
|
29
|
+
import { runs, tasks } from "@trigger.dev/sdk";
|
|
30
|
+
|
|
31
|
+
// Called every time something changes for this account
|
|
32
|
+
export async function onAccountChanged(accountId: string) {
|
|
33
|
+
const active = await runs.list({
|
|
34
|
+
status: ["QUEUED", "EXECUTING"],
|
|
35
|
+
taskIdentifier: ["sync-account"],
|
|
36
|
+
tag: [`account:${accountId}`],
|
|
37
|
+
limit: 1,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (active.data.length > 0) return;
|
|
41
|
+
|
|
42
|
+
await tasks.trigger(
|
|
43
|
+
"sync-account",
|
|
44
|
+
{ accountId },
|
|
45
|
+
{ tags: [`account:${accountId}`] }
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
It has three problems:
|
|
51
|
+
|
|
52
|
+
- **It races.** Two calls can both see "nothing running" and both trigger.
|
|
53
|
+
- **It's expensive.** Every change runs a search, and the search gets slower as you create more runs.
|
|
54
|
+
- **It doesn't collapse bursts.** 100 changes in a second still mean 100 searches.
|
|
55
|
+
|
|
56
|
+
Let Trigger.dev do the coordination instead.
|
|
57
|
+
|
|
58
|
+
**To collapse bursts into one run, use `debounce`.** While a debounced run is still waiting for its delay, triggers with the same key push it back instead of creating new runs:
|
|
59
|
+
|
|
60
|
+
```ts Use debounce
|
|
61
|
+
import { tasks } from "@trigger.dev/sdk";
|
|
62
|
+
|
|
63
|
+
export async function onAccountChanged(accountId: string) {
|
|
64
|
+
await tasks.trigger(
|
|
65
|
+
"sync-account",
|
|
66
|
+
{ accountId },
|
|
67
|
+
{
|
|
68
|
+
debounce: {
|
|
69
|
+
key: `account-${accountId}`,
|
|
70
|
+
delay: "10s",
|
|
71
|
+
// The run uses the payload of the last trigger
|
|
72
|
+
mode: "trailing",
|
|
73
|
+
// Never push it back past 1m after the first trigger
|
|
74
|
+
maxDelay: "1m",
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
<Tip>
|
|
82
|
+
With debounce, one run handles many changes. Have the task read the pending work from your own
|
|
83
|
+
database when it starts, instead of relying on a single trigger's payload.
|
|
84
|
+
</Tip>
|
|
85
|
+
|
|
86
|
+
**To never run two at once for the same key, use a per-key concurrency limit.** Extra runs wait in the queue instead of running in parallel:
|
|
87
|
+
|
|
88
|
+
```ts Use a concurrency limit
|
|
89
|
+
import { task } from "@trigger.dev/sdk";
|
|
90
|
+
|
|
91
|
+
export const syncAccount = task({
|
|
92
|
+
id: "sync-account",
|
|
93
|
+
concurrency: { perKey: 1 },
|
|
94
|
+
run: async ({ accountId }: { accountId: string }) => {
|
|
95
|
+
// ...
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// When triggering
|
|
100
|
+
await syncAccount.trigger({ accountId }, { concurrencyKey: accountId });
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The `concurrency` option requires SDK 4.7.0 or later. See [Concurrency](/concurrency) for details.
|
|
104
|
+
|
|
105
|
+
Debounce only merges triggers into a run that hasn't started yet. Once that run is queued or executing, the next trigger creates a new run. Combine both options so bursts collapse and a new run never overlaps one that's still going.
|
|
106
|
+
|
|
107
|
+
**For exactly one run per piece of work, use an `idempotencyKey`.** See [Using a random idempotency key](#using-a-random-idempotency-key) below.
|
|
108
|
+
|
|
109
|
+
### Using a fixed delay to space out triggers
|
|
110
|
+
|
|
111
|
+
Adding the same `delay` to every trigger doesn't collapse anything. Each trigger still creates its own run. It just starts later:
|
|
112
|
+
|
|
113
|
+
```ts Avoid
|
|
114
|
+
// 100 changes still create 100 runs, each one 30s after its trigger
|
|
115
|
+
await tasks.trigger("sync-account", { accountId }, { delay: "30s" });
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use [`debounce`](#checking-for-active-runs-before-triggering) with the same key instead, so triggers within the delay join one run.
|
|
119
|
+
|
|
120
|
+
### Using a random idempotency key
|
|
121
|
+
|
|
122
|
+
An idempotency key only dedupes triggers that send the same key. A fresh random value on every trigger never matches, so every call creates a new run:
|
|
123
|
+
|
|
124
|
+
```ts Avoid
|
|
125
|
+
await tasks.trigger("sync-account", payload, {
|
|
126
|
+
// Never matches another trigger, so it dedupes nothing
|
|
127
|
+
idempotencyKey: `sync-${crypto.randomUUID()}`,
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Build the key from the thing that should only happen once:
|
|
132
|
+
|
|
133
|
+
```ts Your backend
|
|
134
|
+
import { tasks } from "@trigger.dev/sdk";
|
|
135
|
+
|
|
136
|
+
// One run per change, even if this code runs again within 30 days
|
|
137
|
+
// (the default key lifetime, set with idempotencyKeyTTL)
|
|
138
|
+
await tasks.trigger("process-change", payload, {
|
|
139
|
+
idempotencyKey: `change-${change.id}`,
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
<Note>
|
|
144
|
+
Inside a task, a raw string key is scoped to the current run. To dedupe across runs, create it
|
|
145
|
+
with `idempotencyKeys.create(key, { scope: "global" })`. See [Idempotency](/idempotency) for
|
|
146
|
+
scopes and TTLs.
|
|
147
|
+
</Note>
|
|
148
|
+
|
|
149
|
+
### Polling for a run's status
|
|
150
|
+
|
|
151
|
+
```ts Avoid
|
|
152
|
+
const handle = await tasks.trigger("generate-report", payload);
|
|
153
|
+
|
|
154
|
+
while (true) {
|
|
155
|
+
const run = await runs.retrieve(handle.id);
|
|
156
|
+
if (run.isCompleted) break;
|
|
157
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Inside a task, use [`triggerAndWait()`](/triggering#yourtask-triggerandwait). You don't pay for compute during waits longer than 5 seconds.
|
|
162
|
+
|
|
163
|
+
From your backend, subscribe to the run. The loop ends when the run finishes:
|
|
164
|
+
|
|
165
|
+
```ts Use realtime
|
|
166
|
+
import { runs, tasks } from "@trigger.dev/sdk";
|
|
167
|
+
|
|
168
|
+
const handle = await tasks.trigger("generate-report", payload);
|
|
169
|
+
|
|
170
|
+
for await (const run of runs.subscribeToRun(handle.id)) {
|
|
171
|
+
console.log(run.status);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Polling runs by tag to follow progress
|
|
176
|
+
|
|
177
|
+
Calling `runs.list({ tag })` on a timer to see what a user's or a job's runs are doing repeats the same search every time. Subscribe once instead:
|
|
178
|
+
|
|
179
|
+
```ts Use realtime
|
|
180
|
+
import { runs } from "@trigger.dev/sdk";
|
|
181
|
+
|
|
182
|
+
const tag = `user:${userId}`;
|
|
183
|
+
|
|
184
|
+
for await (const run of runs.subscribeToRunsWithTag(tag)) {
|
|
185
|
+
console.log(run.id, run.status);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
This iterator never completes on its own, so break out of the loop when you're done. In a frontend, use the [React hooks](/realtime/react-hooks/overview).
|
|
190
|
+
|
|
191
|
+
<Note>
|
|
192
|
+
Tag subscriptions only include runs created in the last 24 hours. You can narrow that with the
|
|
193
|
+
`createdAt` option, but not extend it. To follow a specific older run, use
|
|
194
|
+
`runs.subscribeToRun(runId)`.
|
|
195
|
+
</Note>
|
|
196
|
+
|
|
197
|
+
### Counting runs to measure a backlog
|
|
198
|
+
|
|
199
|
+
Listing `QUEUED` runs to count them gets slower as the backlog grows, which is exactly when you need the number. It can also miss runs: queued runs created before the [time window](#when-you-do-need-runs-list) aren't returned. The queue already tracks the count:
|
|
200
|
+
|
|
201
|
+
```ts Use queues.retrieve()
|
|
202
|
+
import { queues } from "@trigger.dev/sdk";
|
|
203
|
+
|
|
204
|
+
// A task's default queue is named after the task ID
|
|
205
|
+
const queue = await queues.retrieve({
|
|
206
|
+
type: "task",
|
|
207
|
+
name: "sync-account",
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
console.log(queue.queued, queue.running);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For a queue shared between tasks, use `{ type: "custom", name: "your-queue-name" }`.
|
|
214
|
+
|
|
215
|
+
## When you do need runs.list()
|
|
216
|
+
|
|
217
|
+
`runs.list()` is the right tool for dashboards, reports, audits, and finding runs to act on in bulk. To keep it fast:
|
|
218
|
+
|
|
219
|
+
- **Pass a time window.** Use the narrowest `period` (or `from`/`to`) that covers what you need, like `period: "1h"`.
|
|
220
|
+
- **Filter by `taskIdentifier`** as well as status or tag.
|
|
221
|
+
- **Stop paginating once you have what you need.** Don't page through every result by default.
|
|
222
|
+
- **Keep it off hot paths.** Don't call it per event, per trigger, or in a tight loop inside a task. If several places need the same answer, cache it.
|
|
223
|
+
|
|
224
|
+
<Warning>
|
|
225
|
+
If you don't pass `period`, `from`, or `to`, only runs created in the last 7 days are searched.
|
|
226
|
+
The window applies to every status, so runs created before it aren't returned even if they're
|
|
227
|
+
still queued or executing. Passing only `to` removes the lower bound, so the search covers every
|
|
228
|
+
run up to that date.
|
|
229
|
+
</Warning>
|
|
230
|
+
|
|
231
|
+
<Note>
|
|
232
|
+
If a query would be too expensive to complete, the API returns a `422` asking you to narrow the
|
|
233
|
+
time window. The SDK doesn't retry it.
|
|
234
|
+
</Note>
|
package/docs/runs/metadata.mdx
CHANGED
|
@@ -74,7 +74,7 @@ This means it's safe to call these methods anywhere in your code, and they will
|
|
|
74
74
|
undefined.
|
|
75
75
|
</Note>
|
|
76
76
|
|
|
77
|
-
These methods also work inside any task lifecycle hook, either attached to the specific task or
|
|
77
|
+
These methods also work inside any task lifecycle hook, either attached to the specific task or registered globally with `tasks.*` (for example in your `init.ts` file).
|
|
78
78
|
|
|
79
79
|
<CodeGroup>
|
|
80
80
|
|
|
@@ -86,7 +86,7 @@ export const myTask = task({
|
|
|
86
86
|
run: async (payload: { message: string }) => {
|
|
87
87
|
// Your run function work here
|
|
88
88
|
},
|
|
89
|
-
|
|
89
|
+
onStartAttempt: async () => {
|
|
90
90
|
metadata.set("progress", 0.5);
|
|
91
91
|
},
|
|
92
92
|
onSuccess: async () => {
|
|
@@ -95,14 +95,11 @@ export const myTask = task({
|
|
|
95
95
|
});
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
```ts
|
|
99
|
-
import {
|
|
98
|
+
```ts init.ts
|
|
99
|
+
import { tasks, metadata } from "@trigger.dev/sdk";
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
onStart: async () => {
|
|
104
|
-
metadata.set("progress", 0.5);
|
|
105
|
-
},
|
|
101
|
+
tasks.onStartAttempt(async () => {
|
|
102
|
+
metadata.set("progress", 0.5);
|
|
106
103
|
});
|
|
107
104
|
```
|
|
108
105
|
|
|
@@ -731,4 +728,4 @@ See the [API reference](/management/runs/retrieve) for more information.
|
|
|
731
728
|
|
|
732
729
|
## Size limit
|
|
733
730
|
|
|
734
|
-
The maximum size of the metadata object is 256KB. If
|
|
731
|
+
The maximum size of the metadata object is 256KB. If an update would exceed this limit, the server rejects it (HTTP 413) and the update is not applied. Inside a task, metadata updates are sent in the background, so the SDK logs a `Failed to flush metadata` error instead of throwing from `metadata.set()` or `metadata.flush()`. If you are self-hosting, you can change the limit with the `TASK_RUN_METADATA_MAXIMUM_SIZE` environment variable (bytes, default 262144). For example, to raise it to 512KB, set `TASK_RUN_METADATA_MAXIMUM_SIZE=524288`.
|
package/docs/runs.mdx
CHANGED
|
@@ -60,7 +60,7 @@ to complete successfully due to an error in the task code.
|
|
|
60
60
|
failed because it exceeded its `maxDuration`.
|
|
61
61
|
|
|
62
62
|
<Icon icon="fire" iconType="solid" color="#E11D48" size={17} /> **Crashed**: The worker process crashed
|
|
63
|
-
during execution (likely due to an Out of Memory error) and won’t be retried.
|
|
63
|
+
during execution (likely due to an Out of Memory error) and won’t be retried, unless `retry.outOfMemory.machine` is set to retry on a larger machine. See [Machines](/machines#retrying-with-a-larger-machine).
|
|
64
64
|
|
|
65
65
|
<Icon icon="bug" iconType="solid" color="#E11D48" size={17} /> **System failure**: An unrecoverable system
|
|
66
66
|
error has occurred.
|
|
@@ -98,7 +98,7 @@ import { runs } from "@trigger.dev/sdk";
|
|
|
98
98
|
|
|
99
99
|
const run = await runs.retrieve("run_1234");
|
|
100
100
|
|
|
101
|
-
if (run.
|
|
101
|
+
if (run.isSuccess) {
|
|
102
102
|
console.log("Run completed successfully");
|
|
103
103
|
}
|
|
104
104
|
```
|
|
@@ -111,7 +111,7 @@ These helpers are also available when subscribing to Realtime run updates:
|
|
|
111
111
|
import { runs } from "@trigger.dev/sdk";
|
|
112
112
|
|
|
113
113
|
for await (const run of runs.subscribeToRun("run_1234")) {
|
|
114
|
-
if (run.
|
|
114
|
+
if (run.isSuccess) {
|
|
115
115
|
console.log("Run completed successfully!");
|
|
116
116
|
break;
|
|
117
117
|
}
|
|
@@ -129,7 +129,7 @@ await yourTask.trigger({ foo: "bar" }, { idempotencyKey: "unique-key" });
|
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
- If a run with the same idempotency key is already in progress, the new trigger will be ignored.
|
|
132
|
-
- If the run
|
|
132
|
+
- If the run completed successfully (or was canceled), the existing run is returned. If it failed or expired, the key is released and triggering again creates a new run.
|
|
133
133
|
|
|
134
134
|
See our [Idempotency docs](/idempotency) for more information.
|
|
135
135
|
|
|
@@ -253,6 +253,12 @@ Similar to `triggerAndWait()`, the `batchTriggerAndWait()` function lets you bat
|
|
|
253
253
|
|
|
254
254
|
#### runs.list()
|
|
255
255
|
|
|
256
|
+
<Warning>
|
|
257
|
+
`runs.list()` is for browsing, reporting, and bulk operations, not for coordinating runs. Don't
|
|
258
|
+
call it before every trigger or poll it in a loop. See [runs.list() best
|
|
259
|
+
practices](/runs/list-best-practices) for what to use instead.
|
|
260
|
+
</Warning>
|
|
261
|
+
|
|
256
262
|
List runs in a specific environment. You can filter the runs by status, created at, task identifier, version, and more:
|
|
257
263
|
|
|
258
264
|
```ts
|
|
@@ -290,7 +296,7 @@ import { runs } from "@trigger.dev/sdk";
|
|
|
290
296
|
const response = await runs.list({
|
|
291
297
|
status: ["QUEUED", "EXECUTING"], // Filter by status
|
|
292
298
|
taskIdentifier: ["my-task", "my-other-task"], // Filter by task identifier
|
|
293
|
-
from: new Date(
|
|
299
|
+
from: new Date(Date.now() - 24 * 60 * 60 * 1000), // Filter by created at (last 24 hours)
|
|
294
300
|
to: new Date(),
|
|
295
301
|
version: "20241127.2", // Filter by deployment version,
|
|
296
302
|
tag: ["tag1", "tag2"], // Filter by tags
|
|
@@ -327,7 +333,7 @@ If you have just triggered a run, you can pass the entire response object to `re
|
|
|
327
333
|
import { runs, tasks } from "@trigger.dev/sdk";
|
|
328
334
|
import type { myTask } from "./trigger/myTask";
|
|
329
335
|
|
|
330
|
-
const response = await tasks.trigger<typeof myTask>({ foo: "bar" });
|
|
336
|
+
const response = await tasks.trigger<typeof myTask>("my-task", { foo: "bar" });
|
|
331
337
|
const run = await runs.retrieve(response);
|
|
332
338
|
|
|
333
339
|
console.log(run.payload.foo); // string
|
|
@@ -346,14 +352,18 @@ await runs.cancel(runId);
|
|
|
346
352
|
|
|
347
353
|
#### runs.replay()
|
|
348
354
|
|
|
349
|
-
Replay a run:
|
|
355
|
+
Replay a run, optionally overriding its payload or options for the new run:
|
|
350
356
|
|
|
351
357
|
```ts
|
|
352
358
|
import { runs } from "@trigger.dev/sdk";
|
|
353
359
|
|
|
354
360
|
await runs.replay(runId);
|
|
361
|
+
|
|
362
|
+
await runs.replay(runId, { payload: { userId: "user_456" }, delay: "10m" });
|
|
355
363
|
```
|
|
356
364
|
|
|
365
|
+
See [Replaying](/replaying#replaying-using-the-sdk) for every option.
|
|
366
|
+
|
|
357
367
|
#### runs.reschedule()
|
|
358
368
|
|
|
359
369
|
Updates a delayed run with a new delay. Only valid when the run is in the DELAYED state.
|
|
@@ -392,5 +402,5 @@ For more on real-time updates, see the [Realtime](/realtime) documentation.
|
|
|
392
402
|
|
|
393
403
|
### Triggering runs for undeployed tasks
|
|
394
404
|
|
|
395
|
-
It's possible to trigger a run for a task that hasn't been deployed yet. The run will enter the "
|
|
405
|
+
It's possible to trigger a run for a task that hasn't been deployed yet. The run will enter the "Pending version" state until the task is deployed. Once deployed, the run will be queued and executed normally.
|
|
396
406
|
This feature is particularly useful in CI/CD pipelines where you want to trigger tasks before the deployment is complete.
|