Skip to content

fix(engine): lockless waitpoint insert for batch items to eliminate lock contention#3232

Merged
ericallam merged 2 commits intomainfrom
feature/tri-7837-batchtriggerandwait-lock-contention-on-parent-run-causes
Mar 17, 2026
Merged

fix(engine): lockless waitpoint insert for batch items to eliminate lock contention#3232
ericallam merged 2 commits intomainfrom
feature/tri-7837-batchtriggerandwait-lock-contention-on-parent-run-causes

Conversation

@ericallam
Copy link
Member

When processing batchTriggerAndWait items, each batch item was acquiring a
Redis lock on the parent run to insert a TaskRunWaitpoint row. With high
concurrency (processingConcurrency=50), this caused LockAcquisitionTimeoutError
(880 errors/24h in prod), orphaned runs, and stuck parent runs.

Since blockRunWithCreatedBatch already transitions the parent to
EXECUTING_WITH_WAITPOINTS before items are processed, the per-item lock is
unnecessary. The new blockRunWithWaitpointLockless method performs only the
idempotent CTE insert and timeout scheduling without acquiring the lock.

…ock contention

When processing batchTriggerAndWait items, each batch item was acquiring a
Redis lock on the parent run to insert a TaskRunWaitpoint row. With high
concurrency (processingConcurrency=50), this caused LockAcquisitionTimeoutError
(880 errors/24h in prod), orphaned runs, and stuck parent runs.

Since blockRunWithCreatedBatch already transitions the parent to
EXECUTING_WITH_WAITPOINTS before items are processed, the per-item lock is
unnecessary. The new blockRunWithWaitpointLockless method performs only the
idempotent CTE insert and timeout scheduling without acquiring the lock.

refs TRI-7837
@changeset-bot
Copy link

changeset-bot bot commented Mar 17, 2026

⚠️ No Changeset found

Latest commit: d840332

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35851702-6810-4094-bd98-1e22a5e7570a

📥 Commits

Reviewing files that changed from the base of the PR and between 34c8400 and d840332.

📒 Files selected for processing (1)
  • internal-packages/run-engine/src/engine/tests/locking.test.ts
✅ Files skipped from review due to trivial changes (1)
  • internal-packages/run-engine/src/engine/tests/locking.test.ts
📜 Recent 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). (27)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)

Walkthrough

Adds a lockless waitpoint insertion path to reduce Redis lock contention for batchTriggerAndWait processing. A new method, blockRunWithWaitpointLockless, was introduced in WaitpointSystem to perform idempotent CTE inserts (ON CONFLICT DO NOTHING) of TaskRunWaitpoint and _WaitpointRunConnections and to enqueue timeout jobs when provided; it intentionally avoids acquiring the parent run lock. The engine trigger flow was changed to call the lockless path for batch items and retain the locked path for non-batch items. The new method was duplicated in the file. The RunLocker test timeout was increased.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description explains the problem, solution, and rationale, but does not follow the required template structure with explicit checklist, testing steps, and changelog sections. Add the template structure including the checklist, explicit Testing and Changelog sections, and verify all checklist items are addressed.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: introducing a lockless waitpoint insert for batch processing to eliminate lock contention.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/tri-7837-batchtriggerandwait-lock-contention-on-parent-run-causes
📝 Coding Plan
  • Generate coding plan for human review comments

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.

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 (3)
internal-packages/run-engine/src/engine/systems/waitpointSystem.ts (2)

540-559: Guard the lockless path with an explicit state invariant check.

This method relies on a strict precondition (parent already in EXECUTING_WITH_WAITPOINTS). Add a fast-fail guard so future call-site drift doesn’t silently create blockers without the corresponding snapshot transition.

Suggested hardening
   async blockRunWithWaitpointLockless({
@@
   }): Promise<void> {
     const prisma = tx ?? this.$.prisma;
     const $waitpoints = typeof waitpoints === "string" ? [waitpoints] : waitpoints;
+    const snapshot = await getLatestExecutionSnapshot(prisma, runId);
+    if (snapshot.executionStatus !== "EXECUTING_WITH_WAITPOINTS") {
+      throw new Error(
+        `blockRunWithWaitpointLockless requires EXECUTING_WITH_WAITPOINTS; got ${snapshot.executionStatus}`
+      );
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal-packages/run-engine/src/engine/systems/waitpointSystem.ts` around
lines 540 - 559, Add a fast-fail state invariant check at the start of
blockRunWithWaitpointLockless: fetch the parent/run record for runId (using the
same prisma client used in the function) and verify its state equals the
expected EXECUTING_WITH_WAITPOINTS constant; if not, throw or return an explicit
error indicating the precondition failed. Place this guard immediately after
resolving prisma and $waitpoints so the function fails fast on incorrect
call-site state drift rather than proceeding to create blockers. Use the
function name blockRunWithWaitpointLockless, the runId param, and the
EXECUTING_WITH_WAITPOINTS state constant to locate where to add the check.

528-605: Add observability instrumentation and crumbs to this new system method.

Please wrap this path with tracer/meter instrumentation (low-cardinality attributes only) and add @crumbs markers around insert + timeout scheduling branches.

As per coding guidelines internal-packages/run-engine/src/engine/systems/**/*.ts: Integrate OpenTelemetry tracer and meter instrumentation in RunEngine systems for observability; and **/*.{ts,tsx,js}: Add crumbs as you write code using // @Crumbscomments or //#region @Crumbs blocks for agentcrumbs debug tracing.

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

In `@internal-packages/run-engine/src/engine/systems/waitpointSystem.ts` around
lines 528 - 605, Wrap the body of blockRunWithWaitpointLockless in an
OpenTelemetry span (use this.$.tracer.startActiveSpan or equivalent) and record
low-cardinality attributes (runId, projectId, batchId, batchIndex,
waitpointsCount, spanIdToComplete, and a boolean batch flag); use a meter
counter to record successful insert attempts and timeout-job scheduling counts.
Place agent-crumbs markers around the CTE insert block and around the timeout
scheduling loop (e.g. // `@crumbs` begin insert, // `@crumbs` end insert, and //
`@crumbs` begin schedule-timeouts, // `@crumbs` end schedule-timeouts). Ensure
exceptions inside the span are recorded and rethrown, and keep waitpoint IDs out
of span attributes to avoid high-cardinality telemetry.
internal-packages/run-engine/src/engine/index.ts (1)

731-756: Add @crumbs tracing to the new batch/non-batch waitpoint branch.

Please add crumbs on this new execution fork so lockless-vs-locked routing is visible in agent debugging traces.

As per coding guidelines **/*.{ts,tsx,js}: Add crumbs as you write code using // @Crumbscomments or //#region @Crumbs blocks for agentcrumbs debug tracing.

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

In `@internal-packages/run-engine/src/engine/index.ts` around lines 731 - 756, The
new branching between lockless and locked waitpoint paths (inside the
surrounding method that calls this.waitpointSystem) lacks `@crumbs` tracing; add
// `@crumbs` comments before the lockless call (blockRunWithWaitpointLockless) and
before the locked call (blockRunWithWaitpoint) so agent traces show which path
was taken. Each crumb should be a single-line comment with a clear message (e.g.
"waitpoint:lockless" vs "waitpoint:locked") and include key context such as
runId (parentTaskRunId), waitpoint id (taskRun.associatedWaitpoint.id) and batch
flag so debugging traces can correlate runs. Place the crumbs immediately above
the respective await calls in the same function so the agentcrumbs tooling picks
them up. Ensure you follow the project's crumb format used elsewhere (// `@crumbs`
...) for consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal-packages/run-engine/src/engine/index.ts`:
- Around line 731-756: The new branching between lockless and locked waitpoint
paths (inside the surrounding method that calls this.waitpointSystem) lacks
`@crumbs` tracing; add // `@crumbs` comments before the lockless call
(blockRunWithWaitpointLockless) and before the locked call
(blockRunWithWaitpoint) so agent traces show which path was taken. Each crumb
should be a single-line comment with a clear message (e.g. "waitpoint:lockless"
vs "waitpoint:locked") and include key context such as runId (parentTaskRunId),
waitpoint id (taskRun.associatedWaitpoint.id) and batch flag so debugging traces
can correlate runs. Place the crumbs immediately above the respective await
calls in the same function so the agentcrumbs tooling picks them up. Ensure you
follow the project's crumb format used elsewhere (// `@crumbs` ...) for
consistency.

In `@internal-packages/run-engine/src/engine/systems/waitpointSystem.ts`:
- Around line 540-559: Add a fast-fail state invariant check at the start of
blockRunWithWaitpointLockless: fetch the parent/run record for runId (using the
same prisma client used in the function) and verify its state equals the
expected EXECUTING_WITH_WAITPOINTS constant; if not, throw or return an explicit
error indicating the precondition failed. Place this guard immediately after
resolving prisma and $waitpoints so the function fails fast on incorrect
call-site state drift rather than proceeding to create blockers. Use the
function name blockRunWithWaitpointLockless, the runId param, and the
EXECUTING_WITH_WAITPOINTS state constant to locate where to add the check.
- Around line 528-605: Wrap the body of blockRunWithWaitpointLockless in an
OpenTelemetry span (use this.$.tracer.startActiveSpan or equivalent) and record
low-cardinality attributes (runId, projectId, batchId, batchIndex,
waitpointsCount, spanIdToComplete, and a boolean batch flag); use a meter
counter to record successful insert attempts and timeout-job scheduling counts.
Place agent-crumbs markers around the CTE insert block and around the timeout
scheduling loop (e.g. // `@crumbs` begin insert, // `@crumbs` end insert, and //
`@crumbs` begin schedule-timeouts, // `@crumbs` end schedule-timeouts). Ensure
exceptions inside the span are recorded and rethrown, and keep waitpoint IDs out
of span attributes to avoid high-cardinality telemetry.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 15f9a942-52b3-4d81-9d6f-83e06f97c480

📥 Commits

Reviewing files that changed from the base of the PR and between dbbe9f7 and 34c8400.

📒 Files selected for processing (3)
  • .server-changes/fix-batch-waitpoint-lock-contention.md
  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
📜 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: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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}: Use task export syntax: export const myTask = task({ id: 'my-task', run: async (payload) => { ... } })
Use Run Engine 2.0 (@internal/run-engine) and redis-worker for all new work - avoid DEPRECATED zodworker (Graphile-worker wrapper)
Prisma 6.14.0 client and schema use PostgreSQL in internal-packages/database - import only from Prisma client

Files:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.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:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: Always import from @trigger.dev/sdk for Trigger.dev tasks - never use @trigger.dev/sdk/v3 or deprecated client.defineJob
Import subpaths only from @trigger.dev/core, never import from root
Add crumbs as you write code using // @crumbs comments or // #region @crumbs blocks for agentcrumbs debug tracing

Files:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
internal-packages/run-engine/src/engine/systems/**/*.ts

📄 CodeRabbit inference engine (internal-packages/run-engine/CLAUDE.md)

Integrate OpenTelemetry tracer and meter instrumentation in RunEngine systems for observability

Files:

  • internal-packages/run-engine/src/engine/systems/waitpointSystem.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: internal-packages/run-engine/CLAUDE.md:0-0
Timestamp: 2026-03-02T12:43:25.254Z
Learning: Use Redis for distributed locks and queues in the RunEngine system via `RunQueue` and `RunLocker` utilities
📚 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 `batch.triggerByTaskAndWait()` to batch trigger tasks by passing task instances and wait for results

Applied to files:

  • .server-changes/fix-batch-waitpoint-lock-contention.md
  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.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 `batch.triggerAndWait()` to batch trigger multiple different tasks and wait for results

Applied to files:

  • .server-changes/fix-batch-waitpoint-lock-contention.md
  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.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 `yourTask.batchTriggerAndWait()` to batch trigger tasks and wait for all results from a parent task

Applied to files:

  • internal-packages/run-engine/src/engine/index.ts
  • internal-packages/run-engine/src/engine/systems/waitpointSystem.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 `runs.subscribeToBatch()` to subscribe to changes for all runs in a batch

Applied to files:

  • internal-packages/run-engine/src/engine/index.ts
📚 Learning: 2026-03-02T12:42:56.114Z
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/services/**/*.server.ts : When editing services that branch on `RunEngineVersion` to support both V1 and V2 (e.g., `cancelTaskRun.server.ts`, `batchTriggerV3.server.ts`), only modify V2 code paths

Applied to files:

  • internal-packages/run-engine/src/engine/index.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 `yourTask.batchTrigger()` to trigger multiple runs of a task from inside another task

Applied to files:

  • internal-packages/run-engine/src/engine/index.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:

  • internal-packages/run-engine/src/engine/index.ts
📚 Learning: 2026-03-13T13:37:49.544Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-13T13:37:49.544Z
Learning: Applies to **/*.{ts,tsx} : Use Run Engine 2.0 (internal/run-engine) and redis-worker for all new work - avoid DEPRECATED zodworker (Graphile-worker wrapper)

Applied to files:

  • internal-packages/run-engine/src/engine/index.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 `batch.trigger()` to trigger multiple different tasks at once from backend code

Applied to files:

  • internal-packages/run-engine/src/engine/index.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 `tasks.batchTrigger()` to trigger multiple runs of a single task with different payloads

Applied to files:

  • internal-packages/run-engine/src/engine/index.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 `yourTask.triggerAndWait()` to trigger a task and wait for its result from a parent task

Applied to files:

  • internal-packages/run-engine/src/engine/index.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 `batch.triggerByTask()` to batch trigger tasks by passing task instances for static task sets

Applied to files:

  • internal-packages/run-engine/src/engine/index.ts
🔇 Additional comments (1)
.server-changes/fix-batch-waitpoint-lock-contention.md (1)

1-6: Clear and actionable release note.

Good summary of the production symptom, root cause, and behavioral change.

@ericallam ericallam marked this pull request as ready for review March 17, 2026 16:29
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@ericallam
Copy link
Member Author

Needs approval

@ericallam ericallam merged commit 411803e into main Mar 17, 2026
41 checks passed
@ericallam ericallam deleted the feature/tri-7837-batchtriggerandwait-lock-contention-on-parent-run-causes branch March 17, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants