Skip to content

feat: add ttl support at task and config levels#3196

Open
nicktrn wants to merge 16 commits intomainfrom
claude/add-ttl-settings-CTYUL
Open

feat: add ttl support at task and config levels#3196
nicktrn wants to merge 16 commits intomainfrom
claude/add-ttl-settings-CTYUL

Conversation

@nicktrn
Copy link
Collaborator

@nicktrn nicktrn commented Mar 9, 2026

Add TTL (time-to-live) defaults at task-level and config-level, with precedence: per-trigger > task > config > dev default (10m).

Docs PR: #3200 (merge after packages are released)

claude added 3 commits March 9, 2026 13:17
Support TTL defaults at both the task definition level and globally in
trigger.config.ts, with per-trigger overrides still taking precedence.

Precedence order: per-trigger TTL > task-level TTL > dev default (10m)

https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
Piggyback on existing BackgroundWorkerTask query in queue resolution
instead of adding a separate findFirst in the hot trigger path.

https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
Document the two-stage resolution pattern and the rule against adding
DB queries to the trigger hot path, so future changes don't regress
trigger throughput.

https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
@changeset-bot
Copy link

changeset-bot bot commented Mar 9, 2026

🦋 Changeset detected

Latest commit: 8e970f0

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

This PR includes changesets to release 28 packages
Name Type
@trigger.dev/sdk Patch
@trigger.dev/core Patch
trigger.dev Patch
@trigger.dev/python Patch
@internal/sdk-compat-tests Patch
d3-chat Patch
references-d3-openai-agents Patch
references-nextjs-realtime Patch
references-realtime-hooks-test Patch
references-realtime-streams Patch
references-telemetry Patch
@trigger.dev/build Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@internal/cache Patch
@internal/clickhouse Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/schedule-engine Patch
@internal/testcontainers Patch
@internal/tracing Patch
@internal/tsql Patch
@internal/zod-worker Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer 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

@nicktrn nicktrn changed the title Add TTL (time-to-live) support at task and config levels feat: add TTL (time-to-live) support at task and config levels Mar 9, 2026
@nicktrn nicktrn changed the title feat: add TTL (time-to-live) support at task and config levels feat: add ttl support at task and config levels Mar 9, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds TTL (time-to-live) support across the stack. New optional ttl on TriggerConfig and CommonTaskOptions, Zod schemas, and Task/TaskResource metadata. CLI entry points apply trigger-level TTL defaults to tasks. Database migration and Prisma schema add ttl to BackgroundWorkerTask; createBackgroundWorker persists TTL. Queue resolution now returns taskTtl via a new helper and QueueProperties includes taskTtl; trigger task execution computes TTL with precedence: body.options.ttl > taskTtl > global/development default. Documentation and package patch bumps included.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides context and implementation details but deviates from the repository's template structure, lacking the Checklist, Testing section, Changelog, and Screenshots sections. Follow the repository template by including all required sections: Checklist, Testing steps, Changelog, and Screenshots. Ensure the description validates against the expected format.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: adding TTL support at task and config levels, matching the changeset's primary objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/add-ttl-settings-CTYUL

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 and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

claude added 2 commits March 9, 2026 15:00
When a caller provides a custom queue name (via options.queue), the queue
concern returned early without looking up the task's TTL. This caused
task-level and config-level TTL to be silently ignored in favor of just
the dev default. Now both the locked-worker+custom-queue and non-locked+
custom-queue paths fetch task TTL via minimal select queries.

https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
apps/webapp/app/runEngine/concerns/queues.server.ts (1)

103-108: ⚠️ Potential issue | 🔴 Critical

Don't let options.queue bypass the locked-task existence check.

getTaskTtl() returns undefined both when the task has no TTL and when the task is missing entirely, so this branch no longer fails like Line 122 does in the no-override path. With a shared queue name, lockToVersion can now accept a task that the selected worker version doesn't contain.

🐛 Suggested fix
-        taskTtl = await this.getTaskTtl(
+        const lockedTask = await this.getTaskTtlRecord(
           request.taskId,
           request.environment.id,
           lockedBackgroundWorker.id
         );
+        if (!lockedTask) {
+          throw new ServiceValidationError(
+            `Task '${request.taskId}' not found on locked version '${lockedBackgroundWorker.version ?? "<unknown>"}'.`
+          );
+        }
+        taskTtl = lockedTask.ttl;
@@
-  private async getTaskTtl(
+  private async getTaskTtlRecord(
     taskId: string,
     environmentId: string,
     workerId: string
-  ): Promise<string | null | undefined> {
-    const task = await this.prisma.backgroundWorkerTask.findFirst({
+  ): Promise<{ ttl: string | null } | null> {
+    return this.prisma.backgroundWorkerTask.findFirst({
       where: {
         workerId,
         runtimeEnvironmentId: environmentId,
         slug: taskId,
       },
       select: { ttl: true },
     });
-    return task?.ttl;
   }
@@
-    return this.getTaskTtl(taskId, environment.id, worker.id);
+    return (await this.getTaskTtlRecord(taskId, environment.id, worker.id))?.ttl;
   }

Also applies to: 245-269

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/runEngine/concerns/queues.server.ts` around lines 103 - 108,
When options.queue is used we currently call getTaskTtl(...) which returns
undefined both for tasks that legitimately have no TTL and for missing tasks,
allowing lockToVersion to accept a task that doesn't exist on the chosen worker
version; fix by explicitly verifying the task exists before proceeding: after
calling getTaskTtl(request.taskId, request.environment.id,
lockedBackgroundWorker.id) check whether the task actually exists (e.g., call
the repository/getter used elsewhere such as a getTask or findTaskById method)
and throw or handle the missing-task case the same way the no-override path
does; apply the same existence check wherever getTaskTtl is used for queue
overrides (including the other block referenced at lines 245-269) so
lockToVersion never proceeds with a non-existent task.
🧹 Nitpick comments (1)
apps/webapp/app/runEngine/concerns/queues.server.ts (1)

180-181: Keep getQueueName() cheap and aligned with the final queue name.

This wrapper now pays for the TTL lookup that getTaskQueueInfo() does and immediately drops it, and unlike Lines 163-170 it returns the pre-sanitized name. A name-only helper would avoid the extra query and keep this method consistent with the actual resolved queue name.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/runEngine/concerns/queues.server.ts` around lines 180 - 181,
getQueueName() is doing an expensive TTL lookup by calling
getTaskQueueInfo(request) and then discarding TTL while returning a
pre-sanitized name; replace that by a cheap name-only path that returns the
final resolved queue name. Change getQueueName() to call or implement a helper
that mirrors the final resolution/sanitization logic (e.g., use
getSanitizedQueueName(request) or extract the name-only branch from
getTaskQueueInfo) so it does not perform TTL/db lookups, and ensure the returned
value matches the same sanitized/normalized string used by getTaskQueueInfo().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/webapp/app/runEngine/concerns/queues.server.ts`:
- Around line 103-108: When options.queue is used we currently call
getTaskTtl(...) which returns undefined both for tasks that legitimately have no
TTL and for missing tasks, allowing lockToVersion to accept a task that doesn't
exist on the chosen worker version; fix by explicitly verifying the task exists
before proceeding: after calling getTaskTtl(request.taskId,
request.environment.id, lockedBackgroundWorker.id) check whether the task
actually exists (e.g., call the repository/getter used elsewhere such as a
getTask or findTaskById method) and throw or handle the missing-task case the
same way the no-override path does; apply the same existence check wherever
getTaskTtl is used for queue overrides (including the other block referenced at
lines 245-269) so lockToVersion never proceeds with a non-existent task.

---

Nitpick comments:
In `@apps/webapp/app/runEngine/concerns/queues.server.ts`:
- Around line 180-181: getQueueName() is doing an expensive TTL lookup by
calling getTaskQueueInfo(request) and then discarding TTL while returning a
pre-sanitized name; replace that by a cheap name-only path that returns the
final resolved queue name. Change getQueueName() to call or implement a helper
that mirrors the final resolution/sanitization logic (e.g., use
getSanitizedQueueName(request) or extract the name-only branch from
getTaskQueueInfo) so it does not perform TTL/db lookups, and ensure the returned
value matches the same sanitized/normalized string used by getTaskQueueInfo().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 16e4fc7d-f97a-4e9a-8b69-1ebc48d4ebed

📥 Commits

Reviewing files that changed from the base of the PR and between 5a68fa0 and 12d5967.

📒 Files selected for processing (2)
  • apps/webapp/CLAUDE.md
  • apps/webapp/app/runEngine/concerns/queues.server.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/webapp/CLAUDE.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: typecheck / typecheck
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: In TypeScript SDK usage, always import from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or use deprecated client.defineJob
Import from @trigger.dev/core subpaths only, never from the root
Use the Run Engine 2.0 (@internal/run-engine) and redis-worker for all new work, not legacy V1 MarQS queue or deprecated V1 functions

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying only server components (apps/webapp/, apps/supervisor/, etc.) with no package changes, add a .server-changes/ file instead of a changeset

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/webapp/**/*.server.ts

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Access environment variables via the env export from app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use metadata methods (set, del, replace, append, remove, increment, decrement, stream, flush) to update metadata during task execution
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/*@(job|queue|worker|background).{ts,tsx} : Use trigger.dev/redis-worker for all new background job implementations, replacing graphile-worker and zodworker
📚 Learning: 2026-03-02T12:42:41.110Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-02T12:42:41.110Z
Learning: Applies to **/*.{ts,tsx} : Use the Run Engine 2.0 (internal/run-engine) and redis-worker for all new work, not legacy V1 MarQS queue or deprecated V1 functions

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-02T12:43:43.173Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/redis-worker/src/queue.ts : Job queue abstraction should be Redis-backed in src/queue.ts

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-03T13:08:03.862Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3166
File: packages/redis-worker/src/fair-queue/index.ts:1114-1121
Timestamp: 2026-03-03T13:08:03.862Z
Learning: In packages/redis-worker/src/fair-queue/index.ts, it's acceptable for the worker queue depth cap check to allow overshooting by up to batchClaimSize messages per iteration, as the next iteration will recheck and prevent sustained growth beyond the limit.

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-02T12:43:43.173Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/redis-worker/src/worker.ts : Worker loop and job processing should implement concurrency control in src/worker.ts

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-02-10T16:18:48.654Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2980
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx:512-515
Timestamp: 2026-02-10T16:18:48.654Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx, environment.queueSizeLimit is a per-queue maximum that is configured at the environment level, not a shared limit across all queues. Each queue can have up to environment.queueSizeLimit items queued independently.

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
🔇 Additional comments (1)
apps/webapp/app/runEngine/concerns/queues.server.ts (1)

145-145: Nice TTL plumbing: the resolved task default now flows end-to-end.

Both the locked default-queue path and the unlocked lookup now surface taskTtl back to the caller, so the downstream precedence logic can stay simple.

Also applies to: 157-159, 172-175, 193-195, 239-242

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/webapp/app/runEngine/concerns/queues.server.ts (1)

212-229: Use logger.debug instead of console.log for consistency.

Lines 213 and 222 use console.log while line 193 (same function context) uses logger.debug. Using console.log bypasses structured logging and log level controls.

♻️ Suggested fix
     if (!task) {
-      console.log("Failed to get queue name: No task found", {
+      logger.debug("Failed to get queue name: No task found", {
         taskId,
         environmentId: environment.id,
       });
 
       return { queueName: overriddenQueueName ?? defaultQueueName };
     }
 
     if (!task.queue) {
-      console.log("Failed to get queue name: No queue found", {
+      logger.debug("Failed to get queue name: No queue found", {
         taskId,
         environmentId: environment.id,
         queueConfig: task.queueConfig,
       });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/runEngine/concerns/queues.server.ts` around lines 212 - 229,
Replace the two console.log calls in the get-queue logic with logger.debug so
logging is consistent and uses structured logger controls: change the first
console.log(...) that logs "Failed to get queue name: No task found" (the branch
checking if (!task)) to logger.debug with the same message and metadata ({
taskId, environmentId: environment.id }) and change the second console.log(...)
in the (!task.queue) branch to logger.debug with the same message and metadata
({ taskId, environmentId: environment.id, queueConfig: task.queueConfig }); keep
the return values and include task.ttl in the second return as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/webapp/app/runEngine/concerns/queues.server.ts`:
- Around line 212-229: Replace the two console.log calls in the get-queue logic
with logger.debug so logging is consistent and uses structured logger controls:
change the first console.log(...) that logs "Failed to get queue name: No task
found" (the branch checking if (!task)) to logger.debug with the same message
and metadata ({ taskId, environmentId: environment.id }) and change the second
console.log(...) in the (!task.queue) branch to logger.debug with the same
message and metadata ({ taskId, environmentId: environment.id, queueConfig:
task.queueConfig }); keep the return values and include task.ttl in the second
return as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1fca5a27-ba81-46a7-8842-bd2527954005

📥 Commits

Reviewing files that changed from the base of the PR and between 12d5967 and d8eaf31.

⛔ Files ignored due to path filters (3)
  • references/hello-world/src/trigger/example.ts is excluded by !references/**
  • references/hello-world/src/trigger/schedule.ts is excluded by !references/**
  • references/hello-world/trigger.config.ts is excluded by !references/**
📒 Files selected for processing (3)
  • apps/webapp/CLAUDE.md
  • apps/webapp/app/runEngine/concerns/queues.server.ts
  • packages/core/src/v3/schemas/resources.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/webapp/CLAUDE.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: In TypeScript SDK usage, always import from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or use deprecated client.defineJob
Import from @trigger.dev/core subpaths only, never from the root
Use the Run Engine 2.0 (@internal/run-engine) and redis-worker for all new work, not legacy V1 MarQS queue or deprecated V1 functions

Files:

  • packages/core/src/v3/schemas/resources.ts
  • apps/webapp/app/runEngine/concerns/queues.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • packages/core/src/v3/schemas/resources.ts
  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • packages/core/src/v3/schemas/resources.ts
  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • packages/core/src/v3/schemas/resources.ts
  • apps/webapp/app/runEngine/concerns/queues.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • packages/core/src/v3/schemas/resources.ts
  • apps/webapp/app/runEngine/concerns/queues.server.ts
packages/core/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/core/CLAUDE.md)

Never import the root package (@trigger.dev/core). Always use subpath imports such as @trigger.dev/core/v3, @trigger.dev/core/v3/utils, @trigger.dev/core/logger, or @trigger.dev/core/schemas

Files:

  • packages/core/src/v3/schemas/resources.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying only server components (apps/webapp/, apps/supervisor/, etc.) with no package changes, add a .server-changes/ file instead of a changeset

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
apps/webapp/**/*.server.ts

📄 CodeRabbit inference engine (apps/webapp/CLAUDE.md)

Access environment variables via the env export from app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/*@(job|queue|worker|background).{ts,tsx} : Use trigger.dev/redis-worker for all new background job implementations, replacing graphile-worker and zodworker
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use metadata methods (set, del, replace, append, remove, increment, decrement, stream, flush) to update metadata during task execution
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Limit task duration using the `maxDuration` property (in seconds)
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: apps/webapp/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:42:56.114Z
Learning: Applies to apps/webapp/app/v3/*Worker.server.ts : New background job workers should use `trigger.dev/redis-worker` (e.g., `commonWorker.server.ts`, `alertsWorker.server.ts`, `batchTriggerWorker.server.ts`), not zodworker or graphile-worker
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Configure task retry behavior using the `retry` property with options like maxAttempts, factor, and timeout values
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation

Applied to files:

  • packages/core/src/v3/schemas/resources.ts
📚 Learning: 2026-03-02T12:42:41.110Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-02T12:42:41.110Z
Learning: Applies to **/*.{ts,tsx} : Use the Run Engine 2.0 (internal/run-engine) and redis-worker for all new work, not legacy V1 MarQS queue or deprecated V1 functions

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-02T12:43:43.173Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/redis-worker/src/queue.ts : Job queue abstraction should be Redis-backed in src/queue.ts

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-02T12:43:43.173Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: packages/redis-worker/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:43.173Z
Learning: Applies to packages/redis-worker/**/redis-worker/src/worker.ts : Worker loop and job processing should implement concurrency control in src/worker.ts

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2026-03-03T13:08:03.862Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3166
File: packages/redis-worker/src/fair-queue/index.ts:1114-1121
Timestamp: 2026-03-03T13:08:03.862Z
Learning: In packages/redis-worker/src/fair-queue/index.ts, it's acceptable for the worker queue depth cap check to allow overshooting by up to batchClaimSize messages per iteration, as the next iteration will recheck and prevent sustained growth beyond the limit.

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/runEngine/concerns/queues.server.ts
🔇 Additional comments (3)
packages/core/src/v3/schemas/resources.ts (1)

16-16: LGTM!

The ttl field is correctly defined to accept either a string (duration format like "10m") or a non-negative number (seconds), matching the pattern used elsewhere in the codebase (e.g., CommonTaskOptions, TaskMetadata). The nonnegative() constraint is appropriate since negative TTL values are semantically invalid.

apps/webapp/app/runEngine/concerns/queues.server.ts (2)

82-102: LGTM! - Properly addresses the TTL resolution for locked workers.

The refactored logic now always fetches the task to retrieve its TTL even when a queue override is provided. This correctly implements the TTL precedence model (trigger-level > task-level > dev default) regardless of queue selection.


166-170: LGTM!

The return structure correctly propagates taskTtl alongside queueName and lockedQueueId. The nullable type (string | null | undefined) correctly models the three states: configured TTL (string), no configuration (null from DB), or unknown (undefined when task not found).

coderabbitai[bot]

This comment was marked as resolved.

@nicktrn nicktrn marked this pull request as ready for review March 11, 2026 15:10
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

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.

3 participants