-
-
Notifications
You must be signed in to change notification settings - Fork 852
New internal idempotency implementation for trigger and batch trigger #2256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis change set introduces a comprehensive internal request idempotency mechanism for trigger and batch trigger operations across the application and SDK. New environment variables and configuration schema entries are added to support Redis-backed idempotency caching, including TTL and log level controls. The web application now intercepts trigger and batch trigger requests with an idempotency key, checks for cached results, and avoids duplicate processing by serving cached responses when available. Supporting utilities and services for idempotency management, including a singleton service instance, are implemented. The SDK and core packages are updated to generate and inject unique idempotency keys into outgoing requests, leveraging new cryptographic utility functions. Dependencies for UUID and cryptography are added where required. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ 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). (25)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/webapp/app/v3/services/triggerTask.server.ts (1)
18-19
: Remove unusedEvt
import
Evt
is imported but never referenced in this module, which will trigger theno-unused-vars
ESLint rule and adds needless bytes to the bundle.-import { Evt } from "evt";
packages/core/src/v3/idempotencyKeys.ts (1)
3-4
: Import path is fine – but guard against multiple dynamic imports
digestSHA256
dynamically importsuncrypto
on every call. Although Node caches modules, theawait import()
still incurs an async micro-task each time.Consider memoising inside
utils/crypto.ts
:let cachedSubtle: SubtleCrypto | undefined; export async function digestSHA256(data: string): Promise<string> { if (!cachedSubtle) { cachedSubtle = globalThis.crypto?.subtle ?? (await import("uncrypto")).subtle; } const hash = await cachedSubtle.digest("SHA-256", new TextEncoder().encode(data)); return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join(""); }This avoids the repeated dynamic-import overhead.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (15)
.changeset/clean-beans-compete.md
(1 hunks)apps/webapp/app/env.server.ts
(1 hunks)apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
(6 hunks)apps/webapp/app/routes/api.v2.tasks.batch.ts
(4 hunks)apps/webapp/app/runEngine/services/batchTrigger.server.ts
(4 hunks)apps/webapp/app/services/requestIdempotency.server.ts
(1 hunks)apps/webapp/app/services/requestIdempotencyInstance.server.ts
(1 hunks)apps/webapp/app/services/unkey/redisCacheStore.server.ts
(2 hunks)apps/webapp/app/utils/requestIdempotency.server.ts
(1 hunks)apps/webapp/app/v3/services/triggerTask.server.ts
(2 hunks)apps/webapp/package.json
(2 hunks)packages/core/package.json
(1 hunks)packages/core/src/v3/apiClient/core.ts
(3 hunks)packages/core/src/v3/idempotencyKeys.ts
(2 hunks)packages/core/src/v3/utils/crypto.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
`apps/webapp/**/*.ts`: In the webapp, all environment variables must be accessed through the `env` export of `env.server.ts`, instead of directly accessing `process.env`.
apps/webapp/**/*.ts
: In the webapp, all environment variables must be accessed through theenv
export ofenv.server.ts
, instead of directly accessingprocess.env
.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/webapp.mdc)
List of files the instruction was applied to:
apps/webapp/app/v3/services/triggerTask.server.ts
apps/webapp/app/services/unkey/redisCacheStore.server.ts
apps/webapp/app/runEngine/services/batchTrigger.server.ts
apps/webapp/app/utils/requestIdempotency.server.ts
apps/webapp/app/services/requestIdempotencyInstance.server.ts
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
apps/webapp/app/services/requestIdempotency.server.ts
apps/webapp/app/routes/api.v2.tasks.batch.ts
apps/webapp/app/env.server.ts
`apps/webapp/**/*.{ts,tsx}`: When importing from `@trigger.dev/core` in the weba...
apps/webapp/**/*.{ts,tsx}
: When importing from@trigger.dev/core
in the webapp, never import from the root@trigger.dev/core
path; always use one of the subpath exports as defined in the package's package.json.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/webapp.mdc)
List of files the instruction was applied to:
apps/webapp/app/v3/services/triggerTask.server.ts
apps/webapp/app/services/unkey/redisCacheStore.server.ts
apps/webapp/app/runEngine/services/batchTrigger.server.ts
apps/webapp/app/utils/requestIdempotency.server.ts
apps/webapp/app/services/requestIdempotencyInstance.server.ts
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
apps/webapp/app/services/requestIdempotency.server.ts
apps/webapp/app/routes/api.v2.tasks.batch.ts
apps/webapp/app/env.server.ts
`**/*.{ts,tsx}`: Always prefer using isomorphic code like fetch, ReadableStream,...
**/*.{ts,tsx}
: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
Use strict mode
No default exports, use function declarations
📄 Source: CodeRabbit Inference Engine (.github/copilot-instructions.md)
List of files the instruction was applied to:
apps/webapp/app/v3/services/triggerTask.server.ts
packages/core/src/v3/idempotencyKeys.ts
apps/webapp/app/services/unkey/redisCacheStore.server.ts
apps/webapp/app/runEngine/services/batchTrigger.server.ts
apps/webapp/app/utils/requestIdempotency.server.ts
apps/webapp/app/services/requestIdempotencyInstance.server.ts
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
packages/core/src/v3/apiClient/core.ts
apps/webapp/app/services/requestIdempotency.server.ts
packages/core/src/v3/utils/crypto.ts
apps/webapp/app/routes/api.v2.tasks.batch.ts
apps/webapp/app/env.server.ts
`{packages/core,apps/webapp}/**/*.{ts,tsx}`: We use zod a lot in packages/core and in the webapp
{packages/core,apps/webapp}/**/*.{ts,tsx}
: We use zod a lot in packages/core and in the webapp
📄 Source: CodeRabbit Inference Engine (.github/copilot-instructions.md)
List of files the instruction was applied to:
apps/webapp/app/v3/services/triggerTask.server.ts
packages/core/src/v3/idempotencyKeys.ts
apps/webapp/app/services/unkey/redisCacheStore.server.ts
apps/webapp/app/runEngine/services/batchTrigger.server.ts
apps/webapp/app/utils/requestIdempotency.server.ts
apps/webapp/app/services/requestIdempotencyInstance.server.ts
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
packages/core/src/v3/apiClient/core.ts
apps/webapp/app/services/requestIdempotency.server.ts
packages/core/src/v3/utils/crypto.ts
apps/webapp/app/routes/api.v2.tasks.batch.ts
apps/webapp/app/env.server.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
apps/webapp/app/v3/services/triggerTask.server.ts (14)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST `export` every task, including subtasks, in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Lifecycle hooks (`init`, `cleanup`, `onStart`, `onSuccess`, `onFailure`, `handleError`) must be defined as properties of the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to trigger.config.ts : Global lifecycle hooks for tasks can be defined in `trigger.config.ts` to apply to all tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : The `run` function must contain the main logic for each Trigger.dev task.
.changeset/clean-beans-compete.md (12)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Each Trigger.dev task must have a unique `id` within your project.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `metadata` API from `@trigger.dev/sdk/v3` to attach, update, and access structured metadata within task runs.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
packages/core/package.json (3)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-06-30T13:21:59.438Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : When importing from `@trigger.dev/core` in the webapp, never import from the root `@trigger.dev/core` path; always use one of the subpath exports as defined in the package's package.json.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-30T13:21:33.994Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : We use zod a lot in packages/core and in the webapp
packages/core/src/v3/idempotencyKeys.ts (1)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
apps/webapp/package.json (3)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-30T13:21:33.994Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : We use zod a lot in packages/core and in the webapp
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-06-30T13:21:59.438Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : When importing from `@trigger.dev/core` in the webapp, never import from the root `@trigger.dev/core` path; always use one of the subpath exports as defined in the package's package.json.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-30T13:21:33.994Z
Learning: Applies to **/*.test.{ts,tsx} : Our tests are all vitest
apps/webapp/app/services/unkey/redisCacheStore.server.ts (2)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to trigger.config.ts : The `trigger.config.ts` file must use `defineConfig` from `@trigger.dev/sdk/v3` to configure project settings, directories, retries, telemetry, runtime, machine settings, log level, max duration, and build options.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to trigger.config.ts : Build extensions for Trigger.dev must be configured in the `build` property of `trigger.config.ts` using provided or custom extensions.
apps/webapp/app/runEngine/services/batchTrigger.server.ts (14)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `metadata` API from `@trigger.dev/sdk/v3` to attach, update, and access structured metadata within task runs.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : The `run` function must contain the main logic for each Trigger.dev task.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Lifecycle hooks (`init`, `cleanup`, `onStart`, `onSuccess`, `onFailure`, `handleError`) must be defined as properties of the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to trigger.config.ts : Global lifecycle hooks for tasks can be defined in `trigger.config.ts` to apply to all tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-30T13:21:33.994Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : We use prisma in internal-packages/database for our database interactions using PostgreSQL
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
apps/webapp/app/utils/requestIdempotency.server.ts (1)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
apps/webapp/app/services/requestIdempotencyInstance.server.ts (2)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-06-30T13:21:59.438Z
Learning: Applies to apps/webapp/**/*.ts : In the webapp, all environment variables must be accessed through the `env` export of `env.server.ts`, instead of directly accessing `process.env`.
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts (14)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `metadata` API from `@trigger.dev/sdk/v3` to attach, update, and access structured metadata within task runs.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Each Trigger.dev task must have a unique `id` within your project.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : The `run` function must contain the main logic for each Trigger.dev task.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : If you are able to generate an example payload for a task, do so.
packages/core/src/v3/apiClient/core.ts (1)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
apps/webapp/app/services/requestIdempotency.server.ts (1)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
apps/webapp/app/routes/api.v2.tasks.batch.ts (14)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `metadata` API from `@trigger.dev/sdk/v3` to attach, update, and access structured metadata within task runs.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Each Trigger.dev task must have a unique `id` within your project.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : If you are able to generate an example payload for a task, do so.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : The `run` function must contain the main logic for each Trigger.dev task.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
apps/webapp/app/env.server.ts (1)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-06-30T13:21:59.438Z
Learning: Applies to apps/webapp/**/*.ts : In the webapp, all environment variables must be accessed through the `env` export of `env.server.ts`, instead of directly accessing `process.env`.
🧬 Code Graph Analysis (4)
packages/core/src/v3/idempotencyKeys.ts (1)
packages/core/src/v3/utils/crypto.ts (1)
digestSHA256
(7-16)
apps/webapp/app/services/unkey/redisCacheStore.server.ts (1)
apps/webapp/app/redis.server.ts (1)
createRedisClient
(17-81)
apps/webapp/app/utils/requestIdempotency.server.ts (3)
apps/webapp/app/services/requestIdempotency.server.ts (1)
requestIdempotencyKey
(117-119)apps/webapp/app/services/requestIdempotencyInstance.server.ts (1)
requestIdempotency
(5-5)packages/core/src/v3/apps/http.ts (1)
json
(65-75)
packages/core/src/v3/apiClient/core.ts (2)
apps/webapp/app/services/requestIdempotency.server.ts (1)
requestIdempotencyKey
(117-119)packages/core/src/v3/utils/crypto.ts (1)
randomUUID
(1-5)
⏰ 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). (25)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (9, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: typecheck / typecheck
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (29)
packages/core/package.json (1)
198-199
: Unconditional dependency onuncrypto
may be unnecessary for Node ≥18
uncrypto
exists mainly to poly-fill WebCrypto in older runtimes. Node 18 and higher already exposeglobalThis.crypto.subtle
; pulling the extra module for every install increases bundle size and a cold-start dynamic import cost.Consider:
- "uncrypto": "^0.1.3", + // Only required when `globalThis.crypto?.subtle` is unavailable. + "uncrypto": "^0.1.3",and changing
utils/crypto.ts
to:const subtle = globalThis.crypto?.subtle ?? (await import("uncrypto")).subtle;so the extra package is loaded only when strictly needed.
Please double-check that all supported environments lack a native
crypto.subtle
before cementing the hard dependency.apps/webapp/package.json (1)
200-202
:uuid@9
is ESM-only – verify CJS build pipelineVersion 9 of
uuid
exports pure ESM. Your server build (esbuild --platform=node --format=cjs
) will bundle it, but any code that usesrequire("uuid")
at runtime will now break.
- Ensure every import is the ESM form:
import { v4 as uuidv4, validate as uuidValidate } from "uuid";
Run a quick grep to catch accidental
require("uuid")
usage.If any third-party code expects CJS, pin to
uuid@8
instead.Also applies to: 243-244
.changeset/clean-beans-compete.md (1)
1-6
: Changeset looks good – Title, semver bump and summary are clear.packages/core/src/v3/idempotencyKeys.ts (1)
118-120
: Function now async-only – confirm all callersawait
it
generateIdempotencyKey
already returned aPromise
, but double-check downstream usages (especially in user-facing helpers) to ensure nothing assumed it was synchronous.apps/webapp/app/services/unkey/redisCacheStore.server.ts (1)
6-9
: LGTM! Clean enhancement for Redis client naming.The addition of the optional
name
property provides better configurability for Redis clients while maintaining backward compatibility with a sensible default.Also applies to: 17-19
packages/core/src/v3/apiClient/core.ts (3)
21-21
: LGTM! Proper import of cryptographic utility.The dynamic import of
randomUUID
from the crypto utils module follows the established pattern.
204-207
: LGTM! Clean idempotency key generation and injection.The implementation correctly generates a unique UUID for each request and injects it at the appropriate point in the request flow. The async/await pattern is properly handled.
634-646
: Well-implemented header injection helper.The function correctly creates a new Headers object and sets the idempotency key header. The function signature and implementation are clean and follow good practices.
apps/webapp/app/runEngine/services/batchTrigger.server.ts (2)
11-11
: LGTM! Proper event emitter setup.The addition of the
Evt
import and public event emitter property follows good event-driven design patterns for the idempotency mechanism.Also applies to: 55-55
173-173
: Excellent event emission timing.The events are emitted immediately after batch creation in both processing paths, which is the correct timing for the idempotency mechanism to capture and cache the batch run information.
Also applies to: 266-266
apps/webapp/app/services/requestIdempotencyInstance.server.ts (2)
1-5
: LGTM! Proper singleton pattern implementation.The singleton pattern is appropriately used for the request idempotency service, ensuring a single instance across the application.
7-22
: Excellent configuration following webapp guidelines.The factory function correctly accesses environment variables through
env.server.ts
as required by the coding guidelines. The Redis configuration is comprehensive and the request types are properly constrained to the expected values.packages/core/src/v3/utils/crypto.ts (2)
1-5
: LGTM! Clean UUID generation utility.The implementation correctly uses dynamic imports and provides a simple, async interface for UUID generation.
7-16
: Excellent SHA-256 implementation.The function properly uses the Web Crypto API via
uncrypto
and implements cross-runtime compatible hex string conversion. The byte-to-hex mapping with zero-padding is correct.apps/webapp/app/routes/api.v2.tasks.batch.ts (4)
7-16
: LGTM! Clean import organization.The imports are well-organized with the new idempotency utilities appropriately grouped.
61-77
: Good addition of idempotency key handling.The request idempotency key is properly extracted from headers and included in debug logging for traceability.
79-105
: Well-structured idempotency check implementation.The cached response handling is clean and follows good patterns:
- Proper database query to find cached batch run
- Correct response building with appropriate headers
- Early return to avoid duplicate processing
113-116
: Effective use of event-driven architecture.Using
attachOnce
ensures the listener is automatically removed after the event fires, preventing memory leaks. The async handler properly saves the idempotency mapping.apps/webapp/app/env.server.ts (1)
936-972
: Well-structured environment configuration.The request idempotency Redis configuration follows the established patterns in this file:
- Appropriate fallbacks to base Redis variables
- Reasonable default TTL of 24 hours
- Configurable log level with sensible default
apps/webapp/app/utils/requestIdempotency.server.ts (3)
1-14
: Well-designed generic idempotency utility.The type definitions and imports are clean. The generic
IdempotencyConfig
type provides good flexibility for different request types while maintaining type safety.
15-70
: Robust idempotency checking with proper observability.The implementation includes:
- Proper null checks for the idempotency key
- Comprehensive tracing with relevant attributes
- Good logging at appropriate levels
- Graceful handling when cached entities are not found
72-84
: Simple and effective save function.The save function appropriately handles the optional idempotency key and delegates to the service.
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts (3)
35-38
: Consistent idempotency header handling.The idempotency key header is properly added and extracted, maintaining consistency with the batch trigger implementation.
Also applies to: 65-66
68-92
: Clean idempotency check implementation.The cached response handling mirrors the batch trigger route appropriately, with proper database querying and response building.
165-166
: Good type optimization in responseHeaders.Changing the parameter type to
Pick<TaskRun, "friendlyId">
improves type safety and makes it clear that only thefriendlyId
is needed.apps/webapp/app/services/requestIdempotency.server.ts (4)
1-25
: Well-structured service with proper dependencies.Good choice of using the Unkey cache library with layered stores for performance and reliability. The type definitions are clean and the default TTL is reasonable.
27-55
: Excellent cache configuration with layered stores.The constructor properly:
- Sets up layered caching for performance (memory) and persistence (Redis)
- Configures appropriate key prefixes to avoid collisions
- Uses the provided TTL for both fresh and stale durations
57-82
: Robust request checking with proper validation.The method includes:
- UUID validation to ensure proper key format
- Comprehensive tracing for observability
- Clear debug logging
- Proper handling of cache misses
117-124
: Appropriate use of UUID v4 for idempotency keys.UUID v4 provides sufficient randomness and uniqueness for idempotency keys. The validation ensures only properly formatted keys are accepted.
🦋 Changeset detectedLatest commit: 10f2365 The changes in this PR will be included in the next version bump. 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts (1)
146-146
: Status code correction is appropriate.The change from 408 to 200 is correct for a successful trigger response. Status 200 is appropriate for successful synchronous operations, though 202 (Accepted) would also be valid for async operations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
(6 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
`apps/webapp/**/*.ts`: In the webapp, all environment variables must be accessed through the `env` export of `env.server.ts`, instead of directly accessing `process.env`.
apps/webapp/**/*.ts
: In the webapp, all environment variables must be accessed through theenv
export ofenv.server.ts
, instead of directly accessingprocess.env
.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/webapp.mdc)
List of files the instruction was applied to:
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
`apps/webapp/**/*.{ts,tsx}`: When importing from `@trigger.dev/core` in the weba...
apps/webapp/**/*.{ts,tsx}
: When importing from@trigger.dev/core
in the webapp, never import from the root@trigger.dev/core
path; always use one of the subpath exports as defined in the package's package.json.
📄 Source: CodeRabbit Inference Engine (.cursor/rules/webapp.mdc)
List of files the instruction was applied to:
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
`**/*.{ts,tsx}`: Always prefer using isomorphic code like fetch, ReadableStream,...
**/*.{ts,tsx}
: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
Use strict mode
No default exports, use function declarations
📄 Source: CodeRabbit Inference Engine (.github/copilot-instructions.md)
List of files the instruction was applied to:
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
`{packages/core,apps/webapp}/**/*.{ts,tsx}`: We use zod a lot in packages/core and in the webapp
{packages/core,apps/webapp}/**/*.{ts,tsx}
: We use zod a lot in packages/core and in the webapp
📄 Source: CodeRabbit Inference Engine (.github/copilot-instructions.md)
List of files the instruction was applied to:
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Each Trigger.dev task must have a unique `id` within your project.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts (15)
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When implementing idempotency, use the `idempotencyKeys` API from `@trigger.dev/sdk/v3` and provide an `idempotencyKey` when triggering tasks.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `metadata` API from `@trigger.dev/sdk/v3` to attach, update, and access structured metadata within task runs.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `runs` and `tasks` APIs from `@trigger.dev/sdk/v3` to subscribe to run updates and implement realtime features.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from backend code, use `tasks.trigger`, `tasks.batchTrigger`, or `tasks.triggerAndPoll` from `@trigger.dev/sdk/v3` and set the `TRIGGER_SECRET_KEY` environment variable.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When triggering a task from inside another task, use the task instance's `trigger`, `batchTrigger`, `triggerAndWait`, `batchTriggerAndWait`, `batch.trigger`, `batch.triggerAndWait`, `batch.triggerByTask`, or `batch.triggerByTaskAndWait` methods.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scheduled tasks must use `schedules.task` from `@trigger.dev/sdk/v3` and define a `cron` property for declarative schedules.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : ALWAYS generate Trigger.dev tasks using the `task` function from `@trigger.dev/sdk/v3` and NEVER use the deprecated `client.defineJob` pattern.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Schema tasks must use `schemaTask` from `@trigger.dev/sdk/v3` and validate payloads using a schema (e.g., Zod).
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Each Trigger.dev task must have a unique `id` within your project.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : The `run` function must contain the main logic for each Trigger.dev task.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : When using retry, queue, machine, or maxDuration options, configure them within the `task` function in Trigger.dev task files.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST NEVER use `client.defineJob` in Trigger.dev task files, as it is deprecated and will break the application.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : If you are able to generate an example payload for a task, do so.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Before generating any code for Trigger.dev tasks, verify that you are importing from `@trigger.dev/sdk/v3`, exporting every task, and not generating any deprecated code patterns.
Learnt from: CR
PR: triggerdotdev/trigger.dev#0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-06-30T13:22:21.528Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : You MUST use `@trigger.dev/sdk/v3` when writing Trigger.dev tasks.
⏰ 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). (20)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (10, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 10)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 10)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 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 (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: typecheck / typecheck
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
apps/webapp/app/routes/api.v1.tasks.$taskId.trigger.ts (5)
9-9
: Import changes look good and follow coding guidelines.The new imports properly use subpath exports from
@trigger.dev/core
and follow the established patterns in the codebase.Also applies to: 12-12, 16-19
35-35
: Header schema correctly adds idempotency key support.The new header field properly defines the idempotency key as nullable string, following the existing pattern.
65-65
: Header extraction properly destructures the new idempotency key.The destructuring follows the established pattern for other headers.
135-135
: Idempotency save logic correctly persists the mapping.The save operation properly stores the idempotency key mapping after successful task trigger.
166-166
: Function signature optimization improves type safety.The change to
Pick<TaskRun, "friendlyId">
is more precise and reflects the actual usage within the function, improving type safety.
Previously, requests to the
batchTrigger
andtrigger
endpoints could be retried (timeouts, 500 errors, etc.) but with the runs/batches already created, which would cause duplicate runs. If inside a task and theandWait
variants were used, this would cause "stuck runs" the parent run would would be blocked by multiple runs (or multiple batches in the case ofbatchTriggerAndWait
. This new system prevents that by introducing a new headerx-trigger-request-idempotency-key
, which is automatically populated by our SDK and stable across retries, which is then used to cache the created entity ID (eitherBatchTaskRun
orTaskRun
) for up to 24 hours.