@trigger.dev/sdk 4.6.4 → 4.7.1
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 +5 -2
- package/dist/commonjs/v3/ai.js +189 -266
- package/dist/commonjs/v3/ai.js.map +1 -1
- package/dist/commonjs/v3/chat-client.js +7 -0
- package/dist/commonjs/v3/chat-client.js.map +1 -1
- package/dist/commonjs/v3/chat-server.d.ts +1 -0
- package/dist/commonjs/v3/chat-server.js +8 -0
- package/dist/commonjs/v3/chat-server.js.map +1 -1
- package/dist/commonjs/v3/chat.d.ts +28 -4
- package/dist/commonjs/v3/chat.js +41 -9
- package/dist/commonjs/v3/chat.js.map +1 -1
- package/dist/commonjs/v3/chatRouteWait.d.ts +21 -0
- package/dist/commonjs/v3/chatRouteWait.js +43 -0
- package/dist/commonjs/v3/chatRouteWait.js.map +1 -0
- package/dist/commonjs/v3/compactionResponse.js +5 -0
- package/dist/commonjs/v3/compactionResponse.js.map +1 -1
- package/dist/commonjs/v3/concurrency-shared.d.ts +13 -0
- package/dist/commonjs/v3/concurrency-shared.js +35 -0
- package/dist/commonjs/v3/concurrency-shared.js.map +1 -0
- package/dist/commonjs/v3/concurrencyLimits.d.ts +73 -0
- package/dist/commonjs/v3/concurrencyLimits.js +166 -0
- package/dist/commonjs/v3/concurrencyLimits.js.map +1 -0
- package/dist/commonjs/v3/index.d.ts +2 -1
- package/dist/commonjs/v3/index.js +3 -1
- package/dist/commonjs/v3/index.js.map +1 -1
- package/dist/commonjs/v3/managedChatResponse.d.ts +44 -0
- package/dist/commonjs/v3/managedChatResponse.js +233 -0
- package/dist/commonjs/v3/managedChatResponse.js.map +1 -0
- package/dist/commonjs/v3/queues.d.ts +31 -0
- package/dist/commonjs/v3/queues.js +31 -0
- package/dist/commonjs/v3/queues.js.map +1 -1
- package/dist/commonjs/v3/shared.d.ts +18 -1
- package/dist/commonjs/v3/shared.js +137 -47
- package/dist/commonjs/v3/shared.js.map +1 -1
- package/dist/commonjs/v3/steeringContext.d.ts +41 -0
- package/dist/commonjs/v3/steeringContext.js +118 -0
- package/dist/commonjs/v3/steeringContext.js.map +1 -0
- package/dist/commonjs/v3/transcriptStorage.d.ts +4 -1
- package/dist/commonjs/v3/transcriptStorage.js +51 -4
- package/dist/commonjs/v3/transcriptStorage.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/esm/v3/ai.d.ts +5 -2
- package/dist/esm/v3/ai.js +189 -266
- package/dist/esm/v3/ai.js.map +1 -1
- package/dist/esm/v3/chat-client.js +7 -0
- package/dist/esm/v3/chat-client.js.map +1 -1
- package/dist/esm/v3/chat-server.d.ts +1 -0
- package/dist/esm/v3/chat-server.js +8 -0
- package/dist/esm/v3/chat-server.js.map +1 -1
- package/dist/esm/v3/chat.d.ts +28 -4
- package/dist/esm/v3/chat.js +41 -9
- package/dist/esm/v3/chat.js.map +1 -1
- package/dist/esm/v3/chatRouteWait.d.ts +21 -0
- package/dist/esm/v3/chatRouteWait.js +40 -0
- package/dist/esm/v3/chatRouteWait.js.map +1 -0
- package/dist/esm/v3/compactionResponse.js +5 -0
- package/dist/esm/v3/compactionResponse.js.map +1 -1
- package/dist/esm/v3/concurrency-shared.d.ts +13 -0
- package/dist/esm/v3/concurrency-shared.js +31 -0
- package/dist/esm/v3/concurrency-shared.js.map +1 -0
- package/dist/esm/v3/concurrencyLimits.d.ts +73 -0
- package/dist/esm/v3/concurrencyLimits.js +158 -0
- package/dist/esm/v3/concurrencyLimits.js.map +1 -0
- package/dist/esm/v3/index.d.ts +2 -1
- package/dist/esm/v3/index.js +2 -1
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/esm/v3/managedChatResponse.d.ts +44 -0
- package/dist/esm/v3/managedChatResponse.js +228 -0
- package/dist/esm/v3/managedChatResponse.js.map +1 -0
- package/dist/esm/v3/queues.d.ts +31 -0
- package/dist/esm/v3/queues.js +31 -0
- package/dist/esm/v3/queues.js.map +1 -1
- package/dist/esm/v3/shared.d.ts +18 -1
- package/dist/esm/v3/shared.js +136 -47
- package/dist/esm/v3/shared.js.map +1 -1
- package/dist/esm/v3/steeringContext.d.ts +41 -0
- package/dist/esm/v3/steeringContext.js +113 -0
- package/dist/esm/v3/steeringContext.js.map +1 -0
- package/dist/esm/v3/transcriptStorage.d.ts +4 -1
- package/dist/esm/v3/transcriptStorage.js +51 -4
- package/dist/esm/v3/transcriptStorage.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/ai-chat/client-protocol.mdx +3 -1
- package/docs/ai-chat/error-handling.mdx +44 -76
- package/docs/ai-chat/fast-starts.mdx +1 -1
- package/docs/ai-chat/frontend.mdx +27 -21
- package/docs/ai-chat/patterns/branching-conversations.mdx +95 -230
- package/docs/ai-chat/patterns/human-in-the-loop.mdx +166 -164
- package/docs/ai-chat/patterns/tool-result-auditing.mdx +28 -27
- package/docs/ai-chat/patterns/version-upgrades.mdx +4 -4
- package/docs/ai-chat/pending-messages.mdx +19 -5
- package/docs/ai-chat/quick-start.mdx +26 -20
- package/docs/ai-chat/reference.mdx +21 -3
- package/docs/ai-chat/sessions.mdx +1 -1
- package/docs/ai-chat/testing.mdx +16 -4
- package/docs/concurrency.mdx +384 -0
- package/docs/config/config-file.mdx +2 -0
- package/docs/database-connections.mdx +3 -3
- package/docs/deploy-environment-variables.mdx +6 -0
- package/docs/deployment/atomic-deployment.mdx +416 -132
- package/docs/deployment/overview.mdx +2 -2
- package/docs/deployment/preview-branches.mdx +2 -2
- package/docs/github-actions.mdx +26 -16
- package/docs/github-integration.mdx +2 -2
- package/docs/idempotency.mdx +43 -5
- package/docs/introduction.mdx +1 -1
- package/docs/limits.mdx +16 -6
- package/docs/manual-setup.mdx +1 -1
- package/docs/observability/query.mdx +25 -0
- package/docs/queues.mdx +271 -0
- package/docs/reports.mdx +1 -1
- package/docs/runs/priority.mdx +2 -25
- package/docs/self-hosting/env/webapp.mdx +9 -0
- package/docs/self-hosting/kubernetes.mdx +14 -3
- package/docs/tasks/overview.mdx +3 -5
- package/docs/troubleshooting-alerts.mdx +124 -1
- package/docs/troubleshooting.mdx +12 -0
- package/docs/vercel-integration.mdx +6 -7
- package/docs/versioning.mdx +1 -1
- package/docs/writing-tasks-introduction.mdx +2 -1
- package/package.json +2 -2
- package/docs/deployment/version-skew-protection.mdx +0 -492
- package/docs/queue-concurrency.mdx +0 -358
|
@@ -123,12 +123,12 @@ jobs:
|
|
|
123
123
|
- name: Deploy preview branch
|
|
124
124
|
run: npx trigger.dev@latest deploy --env preview
|
|
125
125
|
env:
|
|
126
|
-
TRIGGER_ACCESS_TOKEN: ${{ secrets.
|
|
126
|
+
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_PREVIEW_ACCESS_TOKEN }}
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
For this workflow to work, you need to set the following secrets in your GitHub repository:
|
|
130
130
|
|
|
131
|
-
- `
|
|
131
|
+
- `TRIGGER_PREVIEW_ACCESS_TOKEN`: A Trigger.dev API key for the Preview environment with **Deploy only** access. [Create a deployment API key and add it to GitHub](/github-actions#create-a-deployment-api-key).
|
|
132
132
|
|
|
133
133
|
Notice that the deploy command has `--env preview` at the end. We automatically detect the preview branch from the GitHub actions env var.
|
|
134
134
|
|
package/docs/github-actions.mdx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "CI / GitHub Actions"
|
|
3
|
-
description: "
|
|
3
|
+
description: "Deploy your tasks from GitHub Actions and other CI environments using an environment API key."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
The instructions below are specific to GitHub Actions, but the same concepts
|
|
6
|
+
The instructions below are specific to GitHub Actions, but the same concepts apply to other CI systems. Use an environment API key rather than a Personal Access Token so deployments are not tied to an individual team member's account or permissions.
|
|
7
7
|
|
|
8
8
|
<Tip>
|
|
9
9
|
Check out our new [GitHub integration](/github-integration) for automatic deployments, without adding any GitHub Actions workflows.
|
|
@@ -74,7 +74,7 @@ jobs:
|
|
|
74
74
|
|
|
75
75
|
- name: 🚀 Deploy Trigger.dev
|
|
76
76
|
env:
|
|
77
|
-
TRIGGER_ACCESS_TOKEN: ${{ secrets.
|
|
77
|
+
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_STAGING_ACCESS_TOKEN }}
|
|
78
78
|
run: |
|
|
79
79
|
npx trigger.dev@latest deploy --env staging --external-id ${{ github.sha }}
|
|
80
80
|
```
|
|
@@ -85,7 +85,7 @@ If you already have a GitHub action file, you can just add the final step "🚀
|
|
|
85
85
|
|
|
86
86
|
### Pinning runs to the deployment you just built
|
|
87
87
|
|
|
88
|
-
The `--external-id ${{ github.sha }}` above tags the deployment with the commit it was built from. That is the first half of [version skew protection](/deployment/
|
|
88
|
+
The `--external-id ${{ github.sha }}` above tags the deployment with the commit it was built from. That is the first half of [version skew protection](/deployment/atomic-deployment): to complete it, give your running application the **same value** so it sends that id when it triggers.
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
# In your application's runtime environment, for the release built from this commit
|
|
@@ -104,7 +104,7 @@ Every task triggered by that release is then pinned to the deployment built from
|
|
|
104
104
|
`paths:` filter to this workflow, `${{ github.sha }}` stops being a safe id: commits that don't
|
|
105
105
|
touch your tasks never produce a deployment carrying that SHA, so every run from those releases
|
|
106
106
|
expires. See [when nothing ever
|
|
107
|
-
lands](/deployment/
|
|
107
|
+
lands](/deployment/atomic-deployment#when-nothing-ever-lands).
|
|
108
108
|
</Note>
|
|
109
109
|
|
|
110
110
|
## Preview branches
|
|
@@ -135,7 +135,7 @@ jobs:
|
|
|
135
135
|
- name: Deploy preview branch
|
|
136
136
|
run: npx trigger.dev@latest deploy --env preview --external-id ${{ github.event.pull_request.head.sha }}
|
|
137
137
|
env:
|
|
138
|
-
TRIGGER_ACCESS_TOKEN: ${{ secrets.
|
|
138
|
+
TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_PREVIEW_ACCESS_TOKEN }}
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
On `pull_request`, `github.sha` is the merge commit GitHub creates for the PR, not the commit your
|
|
@@ -146,26 +146,36 @@ deployment sends.
|
|
|
146
146
|
**Include `closed`** in the `pull_request.types` list. Without it, preview branches won't be archived when PRs are merged or closed, and you may hit the limit on active preview branches. See [Preview branches](/deployment/preview-branches#preview-branches-with-github-actions-recommended) for more details.
|
|
147
147
|
</Note>
|
|
148
148
|
|
|
149
|
-
##
|
|
149
|
+
## Create a deployment API key
|
|
150
|
+
|
|
151
|
+
Create a separate API key for each environment that your CI workflows deploy to. The key remains valid when team membership or permissions change.
|
|
150
152
|
|
|
151
153
|
<Steps>
|
|
152
154
|
|
|
153
|
-
<Step title="
|
|
154
|
-
|
|
155
|
-
Tokens"](https://cloud.trigger.dev/account/tokens) tab.
|
|
155
|
+
<Step title="Open the API keys page">
|
|
156
|
+
Select the project and target environment, then open [**API keys**](https://cloud.trigger.dev/_/apikeys).
|
|
156
157
|
</Step>
|
|
157
158
|
|
|
158
|
-
<Step title="
|
|
159
|
-
Click
|
|
159
|
+
<Step title="Create an API key">
|
|
160
|
+
Click **New API key**, give the key a name that identifies the workflow, and choose **Deploy
|
|
161
|
+
only** access.
|
|
160
162
|
</Step>
|
|
161
163
|
|
|
162
|
-
<Step title="
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
<Step title="Copy the API key">
|
|
165
|
+
Create the key and copy its value. Trigger.dev shows the complete value only once.
|
|
166
|
+
</Step>
|
|
167
|
+
|
|
168
|
+
<Step title="Add the TRIGGER_ACCESS_TOKEN secret to GitHub">
|
|
169
|
+
Open the repository's **Settings**, then select **Secrets and variables** → **Actions** → **New
|
|
170
|
+
repository secret**. Add the name `TRIGGER_ACCESS_TOKEN` and paste the API key as its value.
|
|
171
|
+
|
|
172
|
+

|
|
165
173
|
</Step>
|
|
166
174
|
|
|
167
175
|
</Steps>
|
|
168
176
|
|
|
177
|
+
The API key must belong to the environment targeted by the deploy command. If the repository deploys to multiple environments, store each environment's key in a separate GitHub secret and map the appropriate secret to `TRIGGER_ACCESS_TOKEN` in each workflow.
|
|
178
|
+
|
|
169
179
|
## CLI Version pinning
|
|
170
180
|
|
|
171
181
|
The CLI and `@trigger.dev/*` package versions need to be in sync with the `trigger.dev` CLI, otherwise there will be errors and unpredictable behavior. Hence, the `deploy` command will automatically fail during CI on any version mismatches.
|
|
@@ -178,7 +188,7 @@ Tip: add the `trigger.dev` CLI to your `devDependencies` and the deploy command
|
|
|
178
188
|
"deploy:trigger": "trigger deploy --env staging"
|
|
179
189
|
},
|
|
180
190
|
"devDependencies": {
|
|
181
|
-
"trigger.dev": "4.0
|
|
191
|
+
"trigger.dev": "4.7.0"
|
|
182
192
|
}
|
|
183
193
|
}
|
|
184
194
|
```
|
|
@@ -74,7 +74,7 @@ The name of the preview branch matches the branch name of the pull request.
|
|
|
74
74
|
|
|
75
75
|
## Version skew protection
|
|
76
76
|
|
|
77
|
-
Every deployment the GitHub integration creates is tagged with the commit SHA it was built from. That is the deploy half of [version skew protection](/deployment/
|
|
77
|
+
Every deployment the GitHub integration creates is tagged with the commit SHA it was built from. That is the deploy half of [version skew protection](/deployment/atomic-deployment) — you get it for free.
|
|
78
78
|
|
|
79
79
|
To complete it, give your running application the same value. Unlike the Vercel integration, we have no access to wherever your app is hosted, so this half is yours to set:
|
|
80
80
|
|
|
@@ -82,7 +82,7 @@ To complete it, give your running application the same value. Unlike the Vercel
|
|
|
82
82
|
TRIGGER_EXTERNAL_DEPLOYMENT_ID=<the-commit-sha-this-release-was-built-from>
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
If your host already exposes the commit SHA at runtime, set `TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION=1` instead and the SDK will find it — see the [platform table](/deployment/
|
|
85
|
+
If your host already exposes the commit SHA at runtime, set `TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION=1` instead and the SDK will find it — see the [platform table](/deployment/atomic-deployment#hosting-platforms).
|
|
86
86
|
|
|
87
87
|
## Disconnecting a repository
|
|
88
88
|
|
package/docs/idempotency.mdx
CHANGED
|
@@ -3,7 +3,9 @@ title: "Idempotency"
|
|
|
3
3
|
description: "An API call or operation is idempotent if it has the same result when called more than once."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Idempotency keys deduplicate task triggers.** If you trigger a task with the same `idempotencyKey` twice, the second request does not create a new run. It returns the original run's handle, so you can track the existing run's progress.
|
|
7
|
+
|
|
8
|
+
The key applies to the trigger call and nothing else. It deduplicates `trigger()`, `triggerAndWait()`, and `batchTrigger()`; it does not make the code inside a task's `run()` function idempotent. See [Side effects inside `run()`](#side-effects-inside-run) for what that means when a task calls an external API.
|
|
7
9
|
|
|
8
10
|
## Why use idempotency keys?
|
|
9
11
|
|
|
@@ -31,10 +33,46 @@ sequenceDiagram
|
|
|
31
33
|
|
|
32
34
|
Other common use cases include:
|
|
33
35
|
|
|
34
|
-
- **Preventing duplicate emails** -
|
|
35
|
-
- **Avoiding double-charging customers** -
|
|
36
|
-
- **One-time setup tasks** -
|
|
37
|
-
- **Deduplicating webhook processing** -
|
|
36
|
+
- **Preventing duplicate emails** - Trigger the email task once, even if the parent task retries
|
|
37
|
+
- **Avoiding double-charging customers** - Trigger the payment task once, even if the parent task retries. The payment API call itself still needs the provider's own idempotency key, see [Side effects inside `run()`](#side-effects-inside-run)
|
|
38
|
+
- **One-time setup tasks** - Trigger initialization or migration tasks once
|
|
39
|
+
- **Deduplicating webhook processing** - Trigger the handler task once per webhook event, even if the event is delivered multiple times
|
|
40
|
+
|
|
41
|
+
## Side effects inside `run()`
|
|
42
|
+
|
|
43
|
+
An idempotency key stops a task from being *triggered* twice. It does not stop the code inside that task from *running* twice. When a run retries, `run()` executes again from the top, and every API call, database write, or email inside it happens again unless that operation is itself idempotent.
|
|
44
|
+
|
|
45
|
+
This matters most for payments. A refund issued directly inside a retryable task is issued again on every retry, even when the retry is caused by an unrelated failure later in the same function. Moving the refund into a child task and triggering it with an idempotency key does not close the gap either: the child is triggered once, but its own `run()` can retry after the provider has accepted the request. Only the provider can deduplicate its own API call.
|
|
46
|
+
|
|
47
|
+
Pass the provider's idempotency key on every call that must happen at most once. Derive it from a value that stays the same across every attempt of the run. The run ID, `ctx.run.id`, always qualifies: retries are attempts of the same run, so the ID does not change between them. This is the same value the default `run` scope mixes into a Trigger.dev idempotency key.
|
|
48
|
+
|
|
49
|
+
```ts /trigger/refund-order.ts
|
|
50
|
+
import { idempotencyKeys, task } from "@trigger.dev/sdk";
|
|
51
|
+
import Stripe from "stripe";
|
|
52
|
+
import { sendRefundEmail } from "./send-refund-email";
|
|
53
|
+
|
|
54
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
|
|
55
|
+
|
|
56
|
+
export const refundOrder = task({
|
|
57
|
+
id: "refund-order",
|
|
58
|
+
retry: { maxAttempts: 3 },
|
|
59
|
+
run: async (payload: { orderId: string; paymentIntentId: string; amount: number }, { ctx }) => {
|
|
60
|
+
// The run ID is stable across retries, so Stripe returns the original refund instead of creating a second one
|
|
61
|
+
await stripe.refunds.create(
|
|
62
|
+
{ payment_intent: payload.paymentIntentId, amount: payload.amount },
|
|
63
|
+
{ idempotencyKey: `refund-${ctx.run.id}` }
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// The Trigger.dev key is run-scoped by default, so a retry does not create a second email run
|
|
67
|
+
const idempotencyKey = await idempotencyKeys.create("refund-email");
|
|
68
|
+
await sendRefundEmail.trigger({ orderId: payload.orderId }, { idempotencyKey });
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The run ID protects against retries of one run. If the same task can be triggered more than once for the same order, either trigger it with a Trigger.dev idempotency key so repeated triggers resolve to the same run and the same run ID, or key the provider call on a business ID from your payload instead, such as `refund-${payload.orderId}`, which deduplicates across separate runs too.
|
|
74
|
+
|
|
75
|
+
Use a Trigger.dev idempotency key to stop a retry triggering a task twice, and the provider's idempotency key to stop a retry calling the provider twice. For a side effect with no idempotency support, record that you performed it in your own database and check that record before performing it again.
|
|
38
76
|
|
|
39
77
|
## `idempotencyKey` option
|
|
40
78
|
|
package/docs/introduction.mdx
CHANGED
|
@@ -51,7 +51,7 @@ Build durable, multi-turn agents with the [chat agent](/ai-chat/overview): one l
|
|
|
51
51
|
|
|
52
52
|
## Scale and scheduling
|
|
53
53
|
|
|
54
|
-
Set how many runs of a task execute at once, globally or per tenant, with [
|
|
54
|
+
Set how many runs of a task execute at once, globally or per tenant, with [concurrency](/concurrency) and [queues](/queues). Run a task on a [cron schedule](/tasks/scheduled) with timezone support, choose the CPU and memory each task runs on with [machines](/machines), and control what happens when a task throws with [errors and retries](/errors-retrying).
|
|
55
55
|
|
|
56
56
|
## Self-hosting
|
|
57
57
|
|
package/docs/limits.mdx
CHANGED
|
@@ -14,11 +14,15 @@ You can view your current limits, quotas, and rate limit usage in real-time by v
|
|
|
14
14
|
|
|
15
15
|
## Concurrency limits
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
17
|
+
Concurrency is allocated **per environment**, not as a single figure for the whole organization. Each plan sets a separate default for production, staging, preview and development:
|
|
18
|
+
|
|
19
|
+
| Pricing tier | Production | Staging | Preview | Development |
|
|
20
|
+
| :----------- | :--------- | :------ | :------ | :---------- |
|
|
21
|
+
| Free | 20 | 10 | 10 | 25 |
|
|
22
|
+
| Hobby | 50 | 25 | 25 | 25 |
|
|
23
|
+
| Pro | 200+ | 100 | 100 | 25 |
|
|
24
|
+
|
|
25
|
+
These are plan defaults. The limit actually enforced for one of your environments can be higher: purchased add-on concurrency and any manual increase we have applied are both included in it. The **Concurrency** page in the dashboard (left sidebar) is authoritative for your organization — if it disagrees with the table above, the dashboard is correct.
|
|
22
26
|
|
|
23
27
|
Extra concurrency above the Pro tier limit is available via the dashboard. Click the "Concurrency" page from the left sidebar when on the Pro plan to purchase more.
|
|
24
28
|
|
|
@@ -50,7 +54,13 @@ The maximum number of runs that can be queued **per queue** (not across all queu
|
|
|
50
54
|
|
|
51
55
|
## Maximum run TTL
|
|
52
56
|
|
|
53
|
-
On Trigger.dev Cloud, all runs have an enforced maximum TTL of 14 days. Runs without an explicit TTL automatically receive the 14-day TTL; runs with a TTL longer than 14 days are clamped to 14 days. This prevents queued runs from accumulating indefinitely.
|
|
57
|
+
On Trigger.dev Cloud, all runs have an enforced maximum TTL of 14 days. Runs without an explicit TTL automatically receive the 14-day TTL; runs with a TTL longer than 14 days are clamped to 14 days. This prevents queued runs from accumulating indefinitely.
|
|
58
|
+
|
|
59
|
+
**The TTL cap does not limit how far ahead you can schedule a run.** TTL governs how long a run may sit *queued* waiting for a concurrency slot. A run triggered with [`delay`](/triggering#delay) is not queued while it is delayed, and no TTL expiry is armed for it — the TTL clock only starts once the delay elapses and the run is enqueued. So scheduling a run a month out with `delay` works fine, and the 14 days then applies to how long it may wait for a slot after that month is up.
|
|
60
|
+
|
|
61
|
+
There is no maximum on `delay`.
|
|
62
|
+
|
|
63
|
+
If you self-host, you can configure a maximum TTL via the `RUN_ENGINE_DEFAULT_MAX_TTL` environment variable — see [Self-hosting environment variables](/self-hosting/env/webapp#run-engine).
|
|
54
64
|
|
|
55
65
|
## Schedules
|
|
56
66
|
|
package/docs/manual-setup.mdx
CHANGED
|
@@ -168,7 +168,7 @@ export default defineConfig({
|
|
|
168
168
|
|
|
169
169
|
### Using the Bun runtime
|
|
170
170
|
|
|
171
|
-
By default, Trigger.dev
|
|
171
|
+
By default, Trigger.dev runs your tasks on the current Node.js LTS. If you're using Bun, you can specify the runtime:
|
|
172
172
|
|
|
173
173
|
```typescript
|
|
174
174
|
import { defineConfig } from "@trigger.dev/sdk";
|
|
@@ -28,6 +28,31 @@ description: "Query allows you to write custom queries against your data using T
|
|
|
28
28
|
|
|
29
29
|
See [Logging, tracing & metrics](/logging#automatic-system-and-runtime-metrics) for the full list of automatically collected metrics and how to create custom metrics. You can visualize this data on [Dashboards](/observability/dashboards).
|
|
30
30
|
|
|
31
|
+
#### API rate limit metrics
|
|
32
|
+
|
|
33
|
+
The `metrics` table also records how the API rate limiter treated requests made with your environment's secret API key, per environment and per `bucket_start` bucket:
|
|
34
|
+
|
|
35
|
+
- `api.rate_limit.allowed` (`sum`): requests that passed the rate limiter
|
|
36
|
+
- `api.rate_limit.denied` (`sum`): requests rejected with a 429
|
|
37
|
+
- `api.rate_limit.remaining_min` (`gauge`): the lowest remaining token count seen in the bucket
|
|
38
|
+
- `api.rate_limit.limit.per_second` (`gauge`): the sustained rate your limit refills at, in requests per second
|
|
39
|
+
- `api.rate_limit.limit.burst` (`gauge`): the most requests the limit admits at once
|
|
40
|
+
|
|
41
|
+
These rows have no run, task, or machine attributes (`run_id`, `task_identifier`, `machine_id` and so on are empty). Sum the counters over time, take `min()` of `api.rate_limit.remaining_min` and `max()` of the limit gauges. Total attempts in a bucket are `allowed + denied`. To draw the sustained limit for a bucket, multiply `api.rate_limit.limit.per_second` by that bucket's width in seconds; `timeBucket()` picks its width from the query's time range, so use a fixed `toStartOfMinute(bucket_start)` grouping when you want a known width (recording buckets never straddle a minute, so this grouping never splits a bucket; the example assumes a bucket width of at most one minute, which includes the default 10 seconds, and with a wider width you would group by that width and multiply by it instead). The limit gauges only exist in buckets that saw requests, and they follow any change to your limit, so a chart stays correct after an increase. Requests from preview branches share the parent preview environment's rate limit bucket and are recorded against that environment, so query at project scope to see them. Self-hosted instances enable recording with `API_RATE_LIMIT_METRICS_ENABLED=1`, or `allowlist` to record only organizations with the `apiRateLimitMetricsEnabled` feature flag.
|
|
42
|
+
|
|
43
|
+
```sql
|
|
44
|
+
SELECT
|
|
45
|
+
toStartOfMinute(bucket_start) AS minute,
|
|
46
|
+
sumIf(metric_value, metric_name IN ('api.rate_limit.allowed', 'api.rate_limit.denied')) AS attempts,
|
|
47
|
+
sumIf(metric_value, metric_name = 'api.rate_limit.denied') AS denied,
|
|
48
|
+
maxIf(metric_value, metric_name = 'api.rate_limit.limit.per_second') * 60 AS limit_per_minute
|
|
49
|
+
FROM metrics
|
|
50
|
+
WHERE metric_name LIKE 'api.rate_limit.%'
|
|
51
|
+
GROUP BY minute
|
|
52
|
+
ORDER BY minute
|
|
53
|
+
LIMIT 1000
|
|
54
|
+
```
|
|
55
|
+
|
|
31
56
|
### `prettyFormat()`
|
|
32
57
|
|
|
33
58
|
Use `prettyFormat()` to format metric values for display:
|
package/docs/queues.mdx
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Queues"
|
|
3
|
+
description: "Control the order your runs execute in."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import Priority from "/snippets/priority.mdx";
|
|
7
|
+
|
|
8
|
+
When you trigger a task, it isn't executed immediately. Instead, the task [run](/runs) is placed into a queue for execution. Runs in a queue are started in the order they were triggered, first in, first out, unless you give a run a [priority](#priority) at trigger time.
|
|
9
|
+
|
|
10
|
+
By default, each task gets its own queue, so triggering the same task ten times executes those runs in trigger order. How many of them execute *at once* is a separate question, governed by [concurrency](/concurrency) — your environment's concurrency limit, plus any limits you set on the task.
|
|
11
|
+
|
|
12
|
+
## Sharing a queue between tasks
|
|
13
|
+
|
|
14
|
+
Declare a queue with `queue()` and set it on several tasks to interleave their runs in one queue. Runs from every task on the queue start in the order they were triggered, whichever task they belong to:
|
|
15
|
+
|
|
16
|
+
```ts /trigger/emails.ts
|
|
17
|
+
import { queue, task } from "@trigger.dev/sdk";
|
|
18
|
+
|
|
19
|
+
const emailQueue = queue({ name: "emails" });
|
|
20
|
+
|
|
21
|
+
export const sendWelcomeEmail = task({
|
|
22
|
+
id: "send-welcome-email",
|
|
23
|
+
queue: emailQueue,
|
|
24
|
+
run: async (payload) => {
|
|
25
|
+
//...
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const sendDigestEmail = task({
|
|
30
|
+
id: "send-digest-email",
|
|
31
|
+
queue: emailQueue,
|
|
32
|
+
run: async (payload) => {
|
|
33
|
+
//...
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
<Note>
|
|
39
|
+
If what you want to share is a concurrency cap rather than ordering, you don't need a shared
|
|
40
|
+
queue: declare a named limit with `concurrencyLimit()` and each task keeps its own queue while
|
|
41
|
+
drawing from the shared limit. See [sharing a limit between
|
|
42
|
+
tasks](/concurrency#sharing-a-limit-between-tasks).
|
|
43
|
+
</Note>
|
|
44
|
+
|
|
45
|
+
Queue names can use letters, numbers, underscores, hyphens and slashes, up to 128 characters. Names starting with `limit/` are reserved for [concurrency limits](/concurrency) and are rejected at deploy time.
|
|
46
|
+
|
|
47
|
+
## Setting the queue when you trigger a run
|
|
48
|
+
|
|
49
|
+
When you trigger a task you can override its queue by name. This is really useful if you sometimes have high priority runs:
|
|
50
|
+
|
|
51
|
+
```ts /trigger/override-queue.ts
|
|
52
|
+
import { queue, task } from "@trigger.dev/sdk";
|
|
53
|
+
|
|
54
|
+
const paidQueue = queue({ name: "paid-users" });
|
|
55
|
+
|
|
56
|
+
export const generatePullRequest = task({
|
|
57
|
+
id: "generate-pull-request",
|
|
58
|
+
// normally this task is limited to 1 run at a time
|
|
59
|
+
concurrency: { total: 1 },
|
|
60
|
+
run: async (payload) => {
|
|
61
|
+
//todo generate a PR using OpenAI
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Triggering from your backend and overriding the queue:
|
|
67
|
+
|
|
68
|
+
```ts app/api/push/route.ts
|
|
69
|
+
import { generatePullRequest } from "~/trigger/override-queue";
|
|
70
|
+
|
|
71
|
+
export async function POST(request: Request) {
|
|
72
|
+
const data = await request.json();
|
|
73
|
+
|
|
74
|
+
if (data.branch === "main") {
|
|
75
|
+
//trigger the task, with the paid users queue
|
|
76
|
+
const handle = await generatePullRequest.trigger(data, {
|
|
77
|
+
// Set the paid users queue
|
|
78
|
+
queue: "paid-users",
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return Response.json(handle);
|
|
82
|
+
} else {
|
|
83
|
+
//triggered with the default queue
|
|
84
|
+
const handle = await generatePullRequest.trigger(data);
|
|
85
|
+
return Response.json(handle);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Priority
|
|
91
|
+
|
|
92
|
+
You can re-order runs within a queue at trigger time by giving them a priority:
|
|
93
|
+
|
|
94
|
+
<Priority />
|
|
95
|
+
|
|
96
|
+
## Archiving queues
|
|
97
|
+
|
|
98
|
+
Queues are created when you deploy, so renaming a queue or deleting a task leaves its old queue behind. To tidy up the list, open the queue's menu on the Concurrency page in the dashboard and choose **Archive**.
|
|
99
|
+
|
|
100
|
+
Archiving only hides the queue in the dashboard, and it doesn't affect runs. Archived queues don't count towards the **Allocated** total, even if they have runs. To see them, turn on the **Show archived** toggle; to bring one back, choose **Unarchive** from its menu.
|
|
101
|
+
|
|
102
|
+
- You can only archive a queue that your current deployment no longer declares.
|
|
103
|
+
- You can't archive a queue while it has runs waiting or in progress, or while it's paused or its concurrency limit or [`total` limit](/concurrency) is 0.
|
|
104
|
+
- If an archived queue gets new runs, it stays hidden, but a warning above the list names it until it's empty.
|
|
105
|
+
- Pausing an archived queue, or setting its concurrency limit or `total` limit to 0 (including by resetting an override), unarchives it.
|
|
106
|
+
- If a later deploy declares the queue again, it's unarchived automatically.
|
|
107
|
+
- The SDK and API still list archived queues.
|
|
108
|
+
|
|
109
|
+
<Note>
|
|
110
|
+
Some runs belong to a queue without currently sitting in it, so they don't count as activity:
|
|
111
|
+
delayed runs that haven't reached their start time yet, runs waiting for a deploy of their
|
|
112
|
+
version, runs that are waiting (for example on `wait.for` or a child task) or have been
|
|
113
|
+
checkpointed, and, depending on how the engine is configured, runs with a concurrency key that
|
|
114
|
+
have been handed to a worker but not picked up yet. A queue with only runs like these can be
|
|
115
|
+
archived, and the warning won't name it until one of them is back in the queue or running. These
|
|
116
|
+
runs still execute normally and always show on the Runs page.
|
|
117
|
+
</Note>
|
|
118
|
+
|
|
119
|
+
## Managing queues with the SDK
|
|
120
|
+
|
|
121
|
+
The SDK provides a `queues` namespace that allows you to manage queues programmatically. You can list, retrieve, pause, resume, and modify concurrency limits for queues.
|
|
122
|
+
|
|
123
|
+
<Note>
|
|
124
|
+
Import from `@trigger.dev/sdk`:
|
|
125
|
+
```ts
|
|
126
|
+
import { queues } from "@trigger.dev/sdk";
|
|
127
|
+
```
|
|
128
|
+
</Note>
|
|
129
|
+
|
|
130
|
+
### Listing queues
|
|
131
|
+
|
|
132
|
+
You can list all queues in your environment with pagination support:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { queues } from "@trigger.dev/sdk";
|
|
136
|
+
|
|
137
|
+
// List all queues (returns paginated results)
|
|
138
|
+
const allQueues = await queues.list();
|
|
139
|
+
|
|
140
|
+
// With pagination options
|
|
141
|
+
const pagedQueues = await queues.list({
|
|
142
|
+
page: 1,
|
|
143
|
+
perPage: 20,
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Retrieving a queue
|
|
148
|
+
|
|
149
|
+
You can retrieve a specific queue by its ID, or by its type and name:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { queues } from "@trigger.dev/sdk";
|
|
153
|
+
|
|
154
|
+
// Using queue ID (starts with "queue_")
|
|
155
|
+
const queueById = await queues.retrieve("queue_1234");
|
|
156
|
+
|
|
157
|
+
// Using type and name for a task's default queue
|
|
158
|
+
const taskQueue = await queues.retrieve({
|
|
159
|
+
type: "task",
|
|
160
|
+
name: "my-task-id",
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Using type and name for a custom queue
|
|
164
|
+
const customQueue = await queues.retrieve({
|
|
165
|
+
type: "custom",
|
|
166
|
+
name: "my-custom-queue",
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
The queue object contains useful information about the queue state, and its `version` discriminates the shape:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// V1: the queue carries its own concurrency limit and override state
|
|
174
|
+
{
|
|
175
|
+
id: "queue_1234", // Queue ID
|
|
176
|
+
name: "my-task-id", // Queue name
|
|
177
|
+
type: "task", // "task" or "custom"
|
|
178
|
+
version: "V1",
|
|
179
|
+
running: 5, // Currently executing runs
|
|
180
|
+
queued: 10, // Runs waiting to execute
|
|
181
|
+
paused: false, // Whether the queue is paused
|
|
182
|
+
concurrencyLimit: 10, // The queue's own limit
|
|
183
|
+
concurrency: {
|
|
184
|
+
current: 10, // Effective limit
|
|
185
|
+
base: 10, // Default limit from code
|
|
186
|
+
override: null, // Override value (if set)
|
|
187
|
+
overriddenAt: null, // When override was applied
|
|
188
|
+
overriddenBy: null, // Who applied the override
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// V2: the queue is only the line runs wait in. Concurrency is declared with
|
|
193
|
+
// the task `concurrency` option and managed through `concurrencyLimits`.
|
|
194
|
+
{
|
|
195
|
+
id: "queue_5678",
|
|
196
|
+
name: "my-v2-task-id",
|
|
197
|
+
type: "task",
|
|
198
|
+
version: "V2",
|
|
199
|
+
running: 3,
|
|
200
|
+
queued: 12,
|
|
201
|
+
paused: false,
|
|
202
|
+
concurrencyLimit: null,
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Pausing and resuming queues
|
|
207
|
+
|
|
208
|
+
You can pause a queue to prevent new runs from starting. Runs that are currently executing will continue to completion.
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { queues } from "@trigger.dev/sdk";
|
|
212
|
+
|
|
213
|
+
// Pause a queue using its ID
|
|
214
|
+
await queues.pause("queue_1234");
|
|
215
|
+
|
|
216
|
+
// Or using type and name
|
|
217
|
+
await queues.pause({ type: "task", name: "my-task-id" });
|
|
218
|
+
await queues.pause({ type: "custom", name: "my-custom-queue" });
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
To resume a paused queue and allow new runs to start:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { queues } from "@trigger.dev/sdk";
|
|
225
|
+
|
|
226
|
+
// Resume a queue using its ID
|
|
227
|
+
await queues.resume("queue_1234");
|
|
228
|
+
|
|
229
|
+
// Or using type and name
|
|
230
|
+
await queues.resume({ type: "task", name: "my-task-id" });
|
|
231
|
+
await queues.resume({ type: "custom", name: "my-custom-queue" });
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Overriding concurrency limits
|
|
235
|
+
|
|
236
|
+
<Warning>
|
|
237
|
+
`queues.overrideConcurrencyLimit` and `queues.resetConcurrencyLimit` are deprecated and only work
|
|
238
|
+
for queues on the legacy model, where the queue carried its own concurrency limit. On the current
|
|
239
|
+
model, declare concurrency with the task `concurrency` option and manage it through
|
|
240
|
+
[`concurrencyLimits`](/concurrency), e.g. `concurrencyLimits.override("task/my-task", { total: 10 })`
|
|
241
|
+
and `concurrencyLimits.reset("task/my-task")`. A legacy limit on a queue used with
|
|
242
|
+
`concurrencyKey` maps to `perKey` rather than `total`, and a limit on a custom queue shared by
|
|
243
|
+
several tasks maps to a named limit declared with `concurrencyLimit()`, again using `perKey`
|
|
244
|
+
when the queue receives keyed runs.
|
|
245
|
+
</Warning>
|
|
246
|
+
|
|
247
|
+
You can temporarily override a queue's concurrency limit. This is useful for scaling up or down based on demand:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
import { queues } from "@trigger.dev/sdk";
|
|
251
|
+
|
|
252
|
+
// Set concurrency limit to 5
|
|
253
|
+
await queues.overrideConcurrencyLimit("queue_1234", 5);
|
|
254
|
+
|
|
255
|
+
// Or using type and name
|
|
256
|
+
await queues.overrideConcurrencyLimit({ type: "task", name: "my-task-id" }, 20);
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
To reset the concurrency limit back to the base value defined in your code:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { queues } from "@trigger.dev/sdk";
|
|
263
|
+
|
|
264
|
+
// Reset concurrency limit to the base value
|
|
265
|
+
await queues.resetConcurrencyLimit("queue_1234");
|
|
266
|
+
|
|
267
|
+
// Or using type and name
|
|
268
|
+
await queues.resetConcurrencyLimit({ type: "task", name: "my-task-id" });
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Overrides survive deploys: redeploying your code keeps an active override until you reset it.
|
package/docs/reports.mdx
CHANGED
|
@@ -148,7 +148,7 @@ An unknown report key returns `404` with the list of available keys.
|
|
|
148
148
|
<Card title="MCP tools" icon="wrench" href="/mcp-tools">
|
|
149
149
|
Every tool the MCP server exposes, including `get_report`.
|
|
150
150
|
</Card>
|
|
151
|
-
<Card title="Concurrency
|
|
151
|
+
<Card title="Concurrency" icon="layer-group" href="/concurrency">
|
|
152
152
|
Configure the concurrency limits the Flow verdict checks against.
|
|
153
153
|
</Card>
|
|
154
154
|
<Card title="Query your data" icon="magnifying-glass" href="/observability/query">
|
package/docs/runs/priority.mdx
CHANGED
|
@@ -3,29 +3,6 @@ title: "Priority"
|
|
|
3
3
|
description: "Specify a priority when triggering a run."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import Priority from "/snippets/priority.mdx";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- You want runs for your premium users to take priority over free users.
|
|
10
|
-
|
|
11
|
-
The value for priority is a time offset in seconds that determines the order of dequeuing.
|
|
12
|
-
|
|
13
|
-

|
|
14
|
-
|
|
15
|
-
If you specify a priority of `10` the run will dequeue before runs that were triggered with no priority 8 seconds ago, like in this example:
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
// no priority = 0
|
|
19
|
-
await myTask.trigger({ foo: "bar" });
|
|
20
|
-
|
|
21
|
-
//... imagine 8s pass by
|
|
22
|
-
|
|
23
|
-
// this run will start before the run above that was triggered 8s ago (with no priority)
|
|
24
|
-
await myTask.trigger({ foo: "bar" }, { priority: 10 });
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
If you passed a value of `3600` the run would dequeue before runs that were triggered an hour ago (with no priority).
|
|
28
|
-
|
|
29
|
-
<Note>
|
|
30
|
-
Setting a high priority will not allow you to beat runs from other organizations. It will only affect the order of your own runs.
|
|
31
|
-
</Note>
|
|
8
|
+
<Priority />
|
|
@@ -23,6 +23,7 @@ mode: "wide"
|
|
|
23
23
|
| **Postgres** | | | |
|
|
24
24
|
| `DATABASE_URL` | Yes | — | PostgreSQL connection string. |
|
|
25
25
|
| `DIRECT_URL` | Yes | — | Direct DB connection string used for migrations etc. |
|
|
26
|
+
| `WEBHOOK_DELIVERIES_REPLICATION_DATABASE_URL` | No | `WEBHOOK_DATABASE_URL`, then `DATABASE_URL` | Direct PostgreSQL connection for webhook delivery replication to ClickHouse. Must target the database containing `WebhookDelivery` and use credentials with replication privileges. Set this when the webhook runtime connection uses a pooler. |
|
|
26
27
|
| `DATABASE_CONNECTION_LIMIT` | No | 10 | Max DB connections. |
|
|
27
28
|
| `DATABASE_POOL_TIMEOUT` | No | 60 | DB pool timeout (s). |
|
|
28
29
|
| `DATABASE_CONNECTION_TIMEOUT` | No | 20 | DB connect timeout (s). |
|
|
@@ -77,6 +78,12 @@ mode: "wide"
|
|
|
77
78
|
| `API_RATE_LIMIT_LIMITER_LOGS_ENABLED` | No | 0 | API rate limit limiter logs. |
|
|
78
79
|
| `API_RATE_LIMIT_JWT_WINDOW` | No | 1m | API rate limit JWT window. |
|
|
79
80
|
| `API_RATE_LIMIT_JWT_TOKENS` | No | 60 | API rate limit JWT tokens. |
|
|
81
|
+
| `API_RATE_LIMIT_METRICS_ENABLED` | No | 0 | Record API rate limit usage into the `metrics` table: `1` for everyone, `allowlist` for flagged organizations. |
|
|
82
|
+
| `API_RATE_LIMIT_METRICS_BUCKET_SECONDS` | No | 10 | Aggregation bucket width for API rate limit metrics: 10, 20, 30 or a multiple of 60. |
|
|
83
|
+
| `API_RATE_LIMIT_METRICS_FLUSH_INTERVAL_MS` | No | 10000 | How often aggregated API rate limit metrics are flushed to ClickHouse. |
|
|
84
|
+
| `API_RATE_LIMIT_METRICS_MAX_ENTRIES` | No | 10000 | Cap on distinct (environment, bucket) entries held between flushes. |
|
|
85
|
+
| `API_RATE_LIMIT_METRICS_WAIT_FOR_ASYNC_INSERT` | No | 0 | Wait for ClickHouse to write each async insert of API rate limit metrics, surfacing write failures. |
|
|
86
|
+
| `API_RATE_LIMIT_METRICS_INSERT_BUSY_TIMEOUT_MS` | No | 10000 | How long ClickHouse buffers API rate limit metric inserts before writing a part. |
|
|
80
87
|
| `DEPLOYMENT_RATE_LIMIT_REFILL_INTERVAL` | No | 10s | Deployment endpoints rate limit refill interval. |
|
|
81
88
|
| `DEPLOYMENT_RATE_LIMIT_MAX` | No | 1500 | Deployment endpoints rate limit max. |
|
|
82
89
|
| `DEPLOYMENT_RATE_LIMIT_REFILL_RATE` | No | 500 | Deployment endpoints rate limit refill rate. |
|
|
@@ -149,6 +156,8 @@ mode: "wide"
|
|
|
149
156
|
| `EVENT_REPOSITORY_DEFAULT_STORE` | No | postgres | Where to store task events. Set to `clickhouse_v2` to store in ClickHouse (recommended for production). |
|
|
150
157
|
| `EVENT_REPOSITORY_POSTGRES_WRITES_DISABLED` | No | 0 | Skip all PostgreSQL task-event writes (set to `1`). Only enable when `EVENT_REPOSITORY_DEFAULT_STORE` is `clickhouse_v2`, otherwise task events are lost. |
|
|
151
158
|
| **Realtime** | | | |
|
|
159
|
+
| `REALTIME_BACKEND_NATIVE_ENABLED` | No | 0 | Set to `1` to enable native realtime run subscriptions and change notifications. When `0`, subscriptions use Electric. The Helm chart sets this to `1`. |
|
|
160
|
+
| `REALTIME_BACKEND_DEFAULT` | No | electric | Backend for run subscriptions when native realtime is enabled and no `realtimeBackend` feature-flag override is set. One of `electric`, `native`, `shadow`. The Helm chart sets this to `native`. Separate from realtime stream version settings. |
|
|
152
161
|
| `REALTIME_STREAM_VERSION` | No | v1 | Stream version exposed to tasks via the `TRIGGER_REALTIME_STREAM_VERSION` variable. Distinct from `REALTIME_STREAMS_DEFAULT_VERSION`. One of `v1`, `v2`. |
|
|
153
162
|
| `REALTIME_STREAM_MAX_LENGTH` | No | 1000 | Realtime stream max length. |
|
|
154
163
|
| `REALTIME_STREAM_TTL` | No | 86400 (1d) | Realtime stream TTL (s). |
|