Skip to content

feat(sdk,core,webapp,run-engine): declare queue gates on tasks and triggers - #4827

Open
matt-aitken wants to merge 3 commits into
feat/queue-gates-enginefrom
feat/queue-gates-contract
Open

feat(sdk,core,webapp,run-engine): declare queue gates on tasks and triggers#4827
matt-aitken wants to merge 3 commits into
feat/queue-gates-enginefrom
feat/queue-gates-contract

Conversation

@matt-aitken

Copy link
Copy Markdown
Member

Summary

Stacked on #4826. Makes queue gates declarable: the queue option on task() and on trigger() now accepts an array where the first entry is the queue the run waits in and up to two more name gates, other queues the run must also hold a concurrency slot in while it executes.

export const tenant = queue({ name: "tenant", concurrencyLimit: 10 });

export const processWebhook = task({
  id: "process-webhook",
  queue: [{ name: "webhooks", concurrencyLimit: 2 }, "tenant"],
  run: async (payload) => {},
});

await processWebhook.trigger(payload, { concurrencyKey: tenantId });

A gate without a concurrencyKey inherits the run's own key (the tenant gate above caps each tenant at 10 across every task that names it); a literal key pins the gate to one shared slot pool (a cap on all traffic to one external provider). A trigger-time array replaces the task's gates for that run. This structure also makes head-of-line blocking benign by construction: a gate's key is always the run's own key or a constant, so a message waiting on a full gate only ever holds up messages that would wait on the same gate.

Design

The SDK normalizes the array into the home queue plus a gates list at its boundaries, so the wire format and storage stay explicit. Task-level gates persist on the worker task record and ride the existing task metadata cache, which keeps the trigger path at its current query count; per-trigger gates arrive in the request options and win over the task's. The resolved list is stored on the run (replays and every payload rebuild reuse it) and flows into the run queue message that #4826 enforces.

Both migrations are additive nullable columns. Covered by an end-to-end engine test (trigger persists gates on the run; a full gate holds the next run queued) plus the existing trigger service tests.

@changeset-bot

changeset-bot Bot commented Aug 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5249200

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 27 packages
Name Type
@trigger.dev/sdk Patch
@trigger.dev/core Patch
@trigger.dev/python Patch
@internal/dashboard-agent Patch
@trigger.dev/build Patch
trigger.dev Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@internal/clickhouse Patch
@internal/llm-model-catalog Patch
@internal/metrics-pipeline Patch
@trigger.dev/rbac Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/run-store Patch
@internal/schedule-engine Patch
@internal/tracing Patch
@internal/webhook-engine Patch
@internal/webhook-sources Patch
@internal/cache Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch
@trigger.dev/sso Patch
@internal/testcontainers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e5b74ac3-9cc8-466f-813b-03a483769b90

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

devin-ai-integration[bot]

This comment was marked as resolved.

@matt-aitken
matt-aitken force-pushed the feat/queue-gates-contract branch from 03c5b34 to d0d9e38 Compare August 29, 2026 09:42
devin-ai-integration[bot]

This comment was marked as resolved.

…iggers

The queue option on task() and on trigger now accepts an array: the first
entry is the queue the run waits in, the rest (at most two) are gates the
run must also hold a concurrency slot in while executing. A gate without a
concurrencyKey inherits the run's own key; a literal key pins the gate to
one shared slot pool. Task-level gates apply to every trigger; a trigger
array replaces them for that run.

Gates persist on BackgroundWorkerTask (task defaults, carried through the
task metadata cache with no extra trigger-time queries) and on TaskRun
(replay fidelity and payload rebuilds), and flow into the run queue message
where the engine enforces them behind its flag.
The queue tuple types now reject more than two gate entries at compile time,
matching the wire schemas. Trigger body construction normalizes the queue
option once per call site through a shared helper instead of three times,
and cached task metadata runs gates through the same parser as database
reads.
@matt-aitken
matt-aitken force-pushed the feat/queue-gates-contract branch from d0d9e38 to 512ff9c Compare August 29, 2026 09:55
…mpty gate names

The dedicated run-ops TaskRun schema gains the same nullable gates column
and migration so run creation keeps working with run-operations splitting
enabled (the schema parity test covers it). Gate names and keys are also
required to be non-empty everywhere they enter, so a configured gate can
never be silently dropped by sanitization.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant