Merge branch 'main' into nicer-app-emails
# Conflicts: # pnpm-lock.yaml
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Added experimental_devProcessCwdInBuildDir config option to opt-in to new process.cwd behavior when executing tasks in the dev CLI. Currently process.cwd maps to the "root" of your trigger.dev project (the directory that contains your trigger.config.ts file). Setting experimental_devProcessCwdInBuildDir to true changes process.cwd to instead be the temporary build directory inside of the .trigger directory.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix dev runs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
fix: importing from runEngine/index.js breaks non-node runtimes
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
The dev command will now use the platform-provided engine URL
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/react-hooks": patch
|
||||
"@trigger.dev/sdk": patch
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/build": patch
|
||||
"@trigger.dev/core": patch
|
||||
"@trigger.dev/rsc": patch
|
||||
---
|
||||
|
||||
Run Engine 2.0 (alpha)
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
fix: Logging large objects is now much more performant and uses less memory
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix update command version mismatch detection
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
New internal idempotency implementation for trigger and batch trigger to prevent request retries from duplicating work
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Add external log exporters and fix missing external trace exporters in deployed tasks
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
When you create a Waitpoint token using `wait.createToken()` you get a URL back that can be used to complete it by making an HTTP POST request.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Allow any runs to finish after SIGTERM but disable warm starts
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Gracefully shutdown task run processes using SIGTERM followed by SIGKILL after a 1s timeout. This also prevents cancelled or completed runs from leaving orphaned Ttask run processes behind
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Enhance deploy command output to better distinguish between local and remote builds
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Configurable queue consumer count in supervisor session
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Switch to profile after successful login
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fixes a bug that would allow processes that had OOM errors to be incorrectly reused when experimental_processKeepAlive was enabled
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Runtime agnostic SDK config via env vars
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/redis-worker": major
|
||||
"@trigger.dev/react-hooks": major
|
||||
"@trigger.dev/sdk": major
|
||||
"trigger.dev": major
|
||||
"@trigger.dev/python": major
|
||||
"@trigger.dev/build": major
|
||||
"@trigger.dev/core": major
|
||||
"@trigger.dev/rsc": major
|
||||
---
|
||||
|
||||
Trigger.dev v4 release. Please see our upgrade to v4 docs to view the full changelog: https://trigger.dev/docs/upgrade-to-v4
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add supervisor http client option to disable debug logs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Fixed an issue with realtime streams that timeout and resume streaming dropping chunks
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Added and cleaned up the run ctx param:
|
||||
|
||||
- New optional properties `ctx.run.parentTaskRunId` and `ctx.run.rootTaskRunId` reference the current run's root/parent ID.
|
||||
- Removed deprecated properties from `ctx`
|
||||
- Added a new `ctx.deployment` object that contains information about the deployment associated with the run.
|
||||
|
||||
We also update `metadata.root` and `metadata.parent` to work even when the run is a "root" run (meaning it doesn't have a parent or a root associated run). This now works:
|
||||
|
||||
```ts
|
||||
metadata.root.set("foo", "bar");
|
||||
metadata.parent.set("baz", 1);
|
||||
metadata.current().foo // "bar"
|
||||
metadata.current().baz // 1
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Expose esbuild `keepNames` option (experimental)
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
The envvars.list() and retrieve() functions receive isSecret for each value. Secret values are always redacted.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add `experimental_autoDetectExternal` trigger config option
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add project details to the whoami command
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Fix issue where realtime streams would cut off after 5 minutes
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Deprecate toolTask and replace with `ai.tool(mySchemaTask)`
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Log images sizes for self-hosted deploys
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Display clickable links in Cursor terminal
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix init.ts in custom trigger dirs
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add import timings and bundle size analysis, the dev command will now warn about slow imports
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Improve structured logs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/build": patch
|
||||
---
|
||||
|
||||
syncVercelEnvVars() fix for syncing the wrong preview branch env vars
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix update command version range handling
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Removes the `releaseConcurrencyOnWaitpoint` option on queues and the `releaseConcurrency` option on various wait functions. Replaced with the following default behavior:
|
||||
|
||||
- Concurrency is never released when a run is first blocked via a waitpoint, at either the env or queue level.
|
||||
- Concurrency is always released when a run is checkpointed and shutdown, at both the env and queue level.
|
||||
|
||||
Additionally, environment concurrency limits now have a new "Burst Factor", defaulting to 2.0x. The "Burst Factor" allows the environment-wide concurrency limit to be higher than any individual queue's concurrency limit. For example, if you have an environment concurrency limit of 100, and a Burst Factor of 2.0x, then you can execute up to 200 runs concurrently, but any one task/queue can still only execute 100 runs concurrently.
|
||||
|
||||
We've done some work cleaning up the run statuses. The new statuses are:
|
||||
|
||||
- `PENDING_VERSION`: Task is waiting for a version update because it cannot execute without additional information (task, queue, etc.)
|
||||
- `QUEUED`: Task is waiting to be executed by a worker
|
||||
- `DEQUEUED`: Task has been dequeued and is being sent to a worker to start executing.
|
||||
- `EXECUTING`: Task is currently being executed by a worker
|
||||
- `WAITING`: Task has been paused by the system, and will be resumed by the system
|
||||
- `COMPLETED`: Task has been completed successfully
|
||||
- `CANCELED`: Task has been canceled by the user
|
||||
- `FAILED`: Task has failed to complete, due to an error in the system
|
||||
- `CRASHED`: Task has crashed and won't be retried, most likely the worker ran out of resources, e.g. memory or storage
|
||||
- `SYSTEM_FAILURE`: Task has failed to complete, due to an error in the system
|
||||
- `DELAYED`: Task has been scheduled to run at a specific time
|
||||
- `EXPIRED`: Task has expired and won't be executed
|
||||
- `TIMED_OUT`: Task has reached it's maxDuration and has been stopped
|
||||
|
||||
We've removed the following statuses:
|
||||
|
||||
- `WAITING_FOR_DEPLOY`: This is no longer used, and is replaced by `PENDING_VERSION`
|
||||
- `FROZEN`: This is no longer used, and is replaced by `WAITING`
|
||||
- `INTERRUPTED`: This is no longer used
|
||||
- `REATTEMPTING`: This is no longer used, and is replaced by `EXECUTING`
|
||||
|
||||
We've also added "boolean" helpers to runs returned via the API and from Realtime:
|
||||
|
||||
- `isQueued`: Returns true when the status is `QUEUED`, `PENDING_VERSION`, or `DELAYED`
|
||||
- `isExecuting`: Returns true when the status is `EXECUTING`, `DEQUEUED`. These count against your concurrency limits.
|
||||
- `isWaiting`: Returns true when the status is `WAITING`. These do not count against your concurrency limits.
|
||||
- `isCompleted`: Returns true when the status is any of the completed statuses.
|
||||
- `isCanceled`: Returns true when the status is `CANCELED`
|
||||
- `isFailed`: Returns true when the status is any of the failed statuses.
|
||||
- `isSuccess`: Returns true when the status is `COMPLETED`
|
||||
|
||||
This change adds the ability to easily detect which runs are being counted against your concurrency limit by filtering for both `EXECUTING` or `DEQUEUED`.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Init command will now correctly install v4-beta packages
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix metadata collapsing correctness
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Improve warm start times by eagerly creating the child TaskRunProcess when a previous run as completed
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
- Resolve issue where CLI could get stuck during deploy finalization
|
||||
- Unify local and remote build logic, with multi-platform build support
|
||||
- Improve switch command; now accepts profile name as an argument
|
||||
- Registry configuration is now fully managed by the webapp
|
||||
- The deploy `--self-hosted` flag is no longer required
|
||||
- Enhance deployment error reporting and image digest retrieval
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/redis-worker": patch
|
||||
---
|
||||
|
||||
Now each worker gets it's own pLimit concurrency limiter, and we will only ever dequeue items where there is concurrency capacity, preventing incorrectly retried jobs due to visibility timeout expiry
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix init.ts detection when using the sentry esbuild plugin
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
- Correctly resolve waitpoints that come in early
|
||||
- Ensure correct state before requesting suspension
|
||||
- Fix race conditions in snapshot processing
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
experimental processKeepAlive
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fixes runLimiter check on #dequeueRuns
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Update nypm package to support test-based bun.lock files
|
||||
@@ -1,104 +0,0 @@
|
||||
{
|
||||
"mode": "pre",
|
||||
"tag": "v4-beta",
|
||||
"initialVersions": {
|
||||
"coordinator": "0.0.1",
|
||||
"docker-provider": "0.0.1",
|
||||
"kubernetes-provider": "0.0.1",
|
||||
"supervisor": "0.0.1",
|
||||
"webapp": "1.0.0",
|
||||
"@trigger.dev/build": "3.3.17",
|
||||
"trigger.dev": "3.3.17",
|
||||
"@trigger.dev/core": "3.3.17",
|
||||
"@trigger.dev/python": "3.3.17",
|
||||
"@trigger.dev/react-hooks": "3.3.17",
|
||||
"@trigger.dev/redis-worker": "3.3.17",
|
||||
"@trigger.dev/rsc": "3.3.17",
|
||||
"@trigger.dev/sdk": "3.3.17"
|
||||
},
|
||||
"changesets": [
|
||||
"beige-horses-juggle",
|
||||
"big-carrots-fail",
|
||||
"big-garlics-own",
|
||||
"blue-eyes-tickle",
|
||||
"breezy-turtles-talk",
|
||||
"chatty-snakes-hope",
|
||||
"chilled-weeks-switch",
|
||||
"clean-beans-compete",
|
||||
"cuddly-boats-press",
|
||||
"curvy-dogs-share",
|
||||
"cyan-news-design",
|
||||
"early-points-jam",
|
||||
"eight-ligers-help",
|
||||
"eighty-rings-divide",
|
||||
"empty-dolls-judge",
|
||||
"fifty-beers-bake",
|
||||
"flat-pianos-live",
|
||||
"four-needles-add",
|
||||
"fuzzy-snakes-beg",
|
||||
"gentle-waves-suffer",
|
||||
"giant-plums-smash",
|
||||
"gold-insects-invite",
|
||||
"green-lions-relate",
|
||||
"grumpy-wasps-fold",
|
||||
"healthy-apricots-drop",
|
||||
"hip-cups-wave",
|
||||
"honest-files-decide",
|
||||
"itchy-frogs-care",
|
||||
"itchy-games-sort",
|
||||
"late-chairs-ring",
|
||||
"late-dancers-smile",
|
||||
"lazy-panthers-shop",
|
||||
"lazy-plums-fetch",
|
||||
"light-peas-melt",
|
||||
"little-birds-appear",
|
||||
"moody-squids-count",
|
||||
"nasty-cobras-wonder",
|
||||
"nice-colts-boil",
|
||||
"ninety-games-grow",
|
||||
"orange-pens-smile",
|
||||
"orange-rocks-grow",
|
||||
"plenty-dolphins-act",
|
||||
"polite-badgers-suffer",
|
||||
"polite-impalas-care",
|
||||
"polite-lies-fix",
|
||||
"rare-beds-accept",
|
||||
"rare-mails-fail",
|
||||
"real-rats-drop",
|
||||
"red-chairs-begin",
|
||||
"red-rings-marry",
|
||||
"red-wasps-cover",
|
||||
"shiny-kiwis-beam",
|
||||
"silly-cows-serve",
|
||||
"silly-timers-repair",
|
||||
"sixty-beers-share",
|
||||
"small-birds-arrive",
|
||||
"small-dancers-smell",
|
||||
"smart-coins-hammer",
|
||||
"smooth-planets-flow",
|
||||
"soft-candles-do",
|
||||
"sour-mirrors-accept",
|
||||
"spotty-ducks-punch",
|
||||
"spotty-pants-wink",
|
||||
"strong-pianos-provide",
|
||||
"sweet-dolphins-invent",
|
||||
"tender-jobs-collect",
|
||||
"thick-bikes-laugh",
|
||||
"tidy-books-smell",
|
||||
"tiny-buckets-teach",
|
||||
"tricky-houses-invite",
|
||||
"twelve-actors-hide",
|
||||
"two-eagles-report",
|
||||
"two-tigers-dream",
|
||||
"weak-jobs-hide",
|
||||
"weak-parents-sip",
|
||||
"wet-deers-think",
|
||||
"wet-dragons-boil",
|
||||
"wet-steaks-reflect",
|
||||
"wicked-ads-walk",
|
||||
"wild-mirrors-return",
|
||||
"witty-cherries-tan",
|
||||
"witty-donkeys-unite",
|
||||
"yellow-cars-tell"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add verbose structured log level
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/build": patch
|
||||
---
|
||||
|
||||
Add Lightpanda extension
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Add onCancel lifecycle hook
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Added AI assistance link when you have build errors
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Provide realtime skipColumns option via untamperable public access tokens
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Suppress external instrumentation for fetch calls from ApiClient
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Handle flush errors gracefully in dev
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Added support for Preview branches in v4 projects
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Can now set project ref using the TRIGGER_PROJECT_REF env var
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Add runtime version detection for display in the dashboard
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/react-hooks": patch
|
||||
---
|
||||
|
||||
Added the ability to specify a "createdAt" filter when subscribing to tags in our useRealtime hooks:
|
||||
|
||||
```tsx
|
||||
// Only subscribe to runs created in the last 10 hours
|
||||
useRealtimeRunWithTags("my-tag", { createdAt: "10h" })
|
||||
```
|
||||
|
||||
You can also now choose to skip subscribing to specific columns by specifying the `skipColumns` option:
|
||||
|
||||
```tsx
|
||||
useRealtimeRun(run.id, { skipColumns: ["usageDurationMs"] });
|
||||
```
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Improve metadata flushing efficiency by collapsing operations
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
fix: Realtime streams: prevent enqueuing into closed ReadableStream
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Update profile switcher
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Update base images to latest compatible versions. The `node-22` runtime now uses v22.16.0 and `bun` uses the latest v1.2.18 release. The default `node` runtime is unchanged and points at v21.7.3.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Improve usage flushing
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
fix: default machine config indexing now works
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Prevent large outputs from overwriting each other
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Fail fast in CI when running deploy with missing `TRIGGER_ACCESS_TOKEN` and add useful error message with link to docs
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Always print full deploy logs in CI
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
TriggerApiError 4xx errors will no longer cause tasks to be retried
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/build": patch
|
||||
---
|
||||
|
||||
Add ffmpeg v7 support to existing extension: `ffmpeg({ version: "7" })`
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
- Fix polling interval reset bug that could create duplicate intervals
|
||||
- Protect against unexpected attempt number changes
|
||||
- Prevent run execution zombies after warm starts
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix stalled run detection
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Managed run controller performance and reliability improvements
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix init.ts auto-import for deployed workers
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Added runs.list filtering for queue and machine
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
maintain proper context in metadata.root and parent getters
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
v4: New lifecycle hooks
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Output esbuild metafile, can be inspected after `deploy --dry run`
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Fix QUEUED status snapshot handler
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Serialize metadata to prevent invalid metadata from breaking run completions
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
If you pass a directory when calling deploy we validate it exists and give helpful hints
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/react-hooks": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Fixes an issue with realtime when re-subscribing to a run, that would temporarily display stale data and the changes. Now when re-subscribing to a run only the latest changes will be vended
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Expose esbuild `minify` option (experimental)
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Fix `syncEnvVars` for non-preview deployments
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/build": patch
|
||||
---
|
||||
|
||||
Add playwright extension
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"@trigger.dev/core": patch
|
||||
---
|
||||
|
||||
Fix Bun runtime path resolution fallback
|
||||
+2
-6
@@ -1,7 +1,3 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"trigger.dev": {
|
||||
"url": "http://localhost:3333/sse"
|
||||
}
|
||||
}
|
||||
}
|
||||
"mcpServers": {}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ alwaysApply: false
|
||||
|
||||
The main trigger.dev webapp, which powers it's API and dashboard and makes up the docker image that is produced as an OSS image, is a Remix 2.1.0 app that uses an express server, written in TypeScript. The following subsystems are either included in the webapp or are used by the webapp in another part of the monorepo:
|
||||
|
||||
- `@trigger.dev/database` exports a Prisma 5.4.1 client that is used extensively in the webapp to access a PostgreSQL instance. The schema file is [schema.prisma](mdc:internal-packages/database/prisma/schema.prisma)
|
||||
- `@trigger.dev/database` exports a Prisma 6.14.0 client that is used extensively in the webapp to access a PostgreSQL instance. The schema file is [schema.prisma](mdc:internal-packages/database/prisma/schema.prisma)
|
||||
- `@trigger.dev/core` is a published package and is used to share code between the `@trigger.dev/sdk` and the webapp. It includes functionality but also a load of Zod schemas for data validation. When importing from `@trigger.dev/core` in the webapp, we never import the root `@trigger.dev/core` path, instead we favor one of the subpath exports that you can find in [package.json](mdc:packages/core/package.json)
|
||||
- `@internal/run-engine` has all the code needed to trigger a run and take it through it's lifecycle to completion.
|
||||
- `@trigger.dev/redis-worker` is a custom redis based background job/worker system that's used in the webapp and also used inside the run engine.
|
||||
@@ -31,7 +31,10 @@ We originally the Trigger.dev "Run Engine" not as a single system, but just spre
|
||||
- The batch trigger API endpoint is [api.v1.tasks.batch.ts](mdc:apps/webapp/app/routes/api.v1.tasks.batch.ts)
|
||||
- Setup code for the prisma client is in [db.server.ts](mdc:apps/webapp/app/db.server.ts)
|
||||
- The run engine is configured in [runEngine.server.ts](mdc:apps/webapp/app/v3/runEngine.server.ts)
|
||||
- All the "services" that are found in app/v3/services/**/*.server.ts
|
||||
- All the "services" that are found in app/v3/services/\*_/_.server.ts
|
||||
- The code for the TaskEvent data, which is the otel data sent from tasks to our servers, is in both the [eventRepository.server.ts](mdc:apps/webapp/app/v3/eventRepository.server.ts) and also the [otlpExporter.server.ts](mdc:apps/webapp/app/v3/otlpExporter.server.ts). The otel endpoints which are hit from production and development otel exporters is [otel.v1.logs.ts](mdc:apps/webapp/app/routes/otel.v1.logs.ts) and [otel.v1.traces.ts](mdc:apps/webapp/app/routes/otel.v1.traces.ts)
|
||||
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/**/*.server.ts
|
||||
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/\*_/_.server.ts
|
||||
|
||||
- All the "services" that are found in app/v3/services/\*_/_.server.ts
|
||||
- The code for the TaskEvent data, which is the otel data sent from tasks to our servers, is in both the [eventRepository.server.ts](mdc:apps/webapp/app/v3/eventRepository.server.ts) and also the [otlpExporter.server.ts](mdc:apps/webapp/app/v3/otlpExporter.server.ts). The otel endpoints which are hit from production and development otel exporters is [otel.v1.logs.ts](mdc:apps/webapp/app/routes/otel.v1.logs.ts) and [otel.v1.traces.ts](mdc:apps/webapp/app/routes/otel.v1.traces.ts)
|
||||
- We use "presenters" to move more complex loader code into a class, and you can find those are app/v3/presenters/\*_/_.server.ts
|
||||
|
||||
@@ -431,28 +431,6 @@ export async function POST(request: Request) {
|
||||
}
|
||||
```
|
||||
|
||||
### tasks.triggerAndPoll()
|
||||
|
||||
Triggers a task and polls until completion. Not recommended for web requests as it blocks until the run completes. Consider using Realtime docs for better alternatives.
|
||||
|
||||
```ts
|
||||
import { tasks } from "@trigger.dev/sdk/v3";
|
||||
import type { emailSequence } from "~/trigger/emails";
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const data = await request.json();
|
||||
const result = await tasks.triggerAndPoll<typeof emailSequence>(
|
||||
"email-sequence",
|
||||
{
|
||||
to: data.email,
|
||||
name: data.name,
|
||||
},
|
||||
{ pollIntervalMs: 5000 }
|
||||
);
|
||||
return Response.json(result);
|
||||
}
|
||||
```
|
||||
|
||||
### batch.trigger()
|
||||
|
||||
Triggers multiple runs of different tasks at once, useful when you need to execute multiple tasks simultaneously.
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
**/dist
|
||||
**/node_modules
|
||||
|
||||
**/generated/prisma
|
||||
|
||||
apps/webapp/build
|
||||
apps/webapp/public/build
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
DIRECT_URL: postgresql://postgres:postgres@localhost:5432/postgres
|
||||
SESSION_SECRET: "secret"
|
||||
MAGIC_LINK_SECRET: "secret"
|
||||
ENCRYPTION_KEY: "secret"
|
||||
ENCRYPTION_KEY: "dummy-encryption-keeeey-32-bytes"
|
||||
DEPLOY_REGISTRY_HOST: "docker.io"
|
||||
CLICKHOUSE_URL: "http://default:password@localhost:8123"
|
||||
|
||||
|
||||
+2
-1
@@ -63,4 +63,5 @@ apps/**/public/build
|
||||
/packages/core/src/package.json
|
||||
/packages/trigger-sdk/src/package.json
|
||||
/packages/python/src/package.json
|
||||
.claude
|
||||
.claude
|
||||
.mcp.log
|
||||
Vendored
+5
-5
@@ -59,7 +59,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug V3 Dev CLI",
|
||||
"command": "pnpm exec trigger dev",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"cwd": "${workspaceFolder}/references/hello-world",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
@@ -83,7 +83,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug V3 Deploy CLI",
|
||||
"command": "pnpm exec trigger deploy --self-hosted --load-image",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"cwd": "${workspaceFolder}/references/hello-world",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
@@ -91,7 +91,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug V3 list-profiles CLI",
|
||||
"command": "pnpm exec trigger list-profiles --log-level debug",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"cwd": "${workspaceFolder}/references/hello-world",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
@@ -99,7 +99,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug V3 update CLI",
|
||||
"command": "pnpm exec trigger update",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"cwd": "${workspaceFolder}/references/hello-world",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
@@ -107,7 +107,7 @@
|
||||
"request": "launch",
|
||||
"name": "Debug V3 Management",
|
||||
"command": "pnpm run management",
|
||||
"cwd": "${workspaceFolder}/references/v3-catalog",
|
||||
"cwd": "${workspaceFolder}/references/hello-world",
|
||||
"sourceMaps": true
|
||||
},
|
||||
{
|
||||
|
||||
+15
-70
@@ -84,17 +84,17 @@ branch are tagged into a release periodically.
|
||||
|
||||
2. Once the app is running click the magic link button and enter your email. You will automatically be logged in, since you are running locally. Create an Org and your first project in the dashboard.
|
||||
|
||||
## Manual testing using v3-catalog
|
||||
## Manual testing using hello-world
|
||||
|
||||
We use the `<root>/references/v3-catalog` subdirectory as a staging ground for testing changes to the SDK (`@trigger.dev/sdk` at `<root>/packages/trigger-sdk`), the Core package (`@trigger.dev/core` at `<root>packages/core`), the CLI (`trigger.dev` at `<root>/packages/cli-v3`) and the platform (The remix app at `<root>/apps/webapp`). The instructions below will get you started on using the `v3-catalog` for local development of Trigger.dev (v3).
|
||||
We use the `<root>/references/hello-world` subdirectory as a staging ground for testing changes to the SDK (`@trigger.dev/sdk` at `<root>/packages/trigger-sdk`), the Core package (`@trigger.dev/core` at `<root>packages/core`), the CLI (`trigger.dev` at `<root>/packages/cli-v3`) and the platform (The remix app at `<root>/apps/webapp`). The instructions below will get you started on using the `hello-world` for local development of Trigger.dev.
|
||||
|
||||
### First-time setup
|
||||
|
||||
First, make sure you are running the webapp according to the instructions above. Then:
|
||||
|
||||
1. Visit http://localhost:3030 in your browser and create a new V3 project called "v3-catalog".
|
||||
1. Visit http://localhost:3030 in your browser and create a new V3 project called "hello-world".
|
||||
|
||||
2. In Postgres go to the "Projects" table and for the project you create change the `externalRef` to `yubjwjsfkxnylobaqvqz`.
|
||||
2. In Postgres go to the "Projects" table and for the project you create change the `externalRef` to `proj_rrkpdguyagvsoktglnod`.
|
||||
|
||||
3. Build the CLI
|
||||
|
||||
@@ -105,10 +105,10 @@ pnpm run build --filter trigger.dev
|
||||
pnpm i
|
||||
```
|
||||
|
||||
4. Change into the `<root>/references/v3-catalog` directory and authorize the CLI to the local server:
|
||||
4. Change into the `<root>/references/hello-world` directory and authorize the CLI to the local server:
|
||||
|
||||
```sh
|
||||
cd references/v3-catalog
|
||||
cd references/hello-world
|
||||
cp .env.example .env
|
||||
pnpm exec trigger login -a http://localhost:3030
|
||||
```
|
||||
@@ -118,7 +118,7 @@ This will open a new browser window and authorize the CLI against your local use
|
||||
You can optionally pass a `--profile` flag to the `login` command, which will allow you to use the CLI with separate accounts/servers. We suggest using a profile called `local` for your local development:
|
||||
|
||||
```sh
|
||||
cd references/v3-catalog
|
||||
cd references/hello-world
|
||||
pnpm exec trigger login -a http://localhost:3030 --profile local
|
||||
# later when you run the dev or deploy command:
|
||||
pnpm exec trigger dev --profile local
|
||||
@@ -137,84 +137,29 @@ The following steps should be followed any time you start working on a new featu
|
||||
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*"
|
||||
```
|
||||
|
||||
3. Open another terminal window, and change into the `<root>/references/v3-catalog` directory.
|
||||
3. Open another terminal window, and change into the `<root>/references/hello-world` directory.
|
||||
|
||||
4. You'll need to run the following commands to setup prisma and migrate the database:
|
||||
4. Run the `dev` command, which will register all the local tasks with the platform and allow you to start testing task execution:
|
||||
|
||||
```sh
|
||||
pnpm exec prisma migrate deploy
|
||||
pnpm run generate:prisma
|
||||
```
|
||||
|
||||
5. Run the `dev` command, which will register all the local tasks with the platform and allow you to start testing task execution:
|
||||
|
||||
```sh
|
||||
# in <root>/references/v3-catalog
|
||||
# in <root>/references/hello-world
|
||||
pnpm exec trigger dev
|
||||
```
|
||||
|
||||
If you want additional debug logging, you can use the `--log-level debug` flag:
|
||||
|
||||
```sh
|
||||
# in <root>/references/v3-catalog
|
||||
# in <root>/references/hello-world
|
||||
pnpm exec trigger dev --log-level debug
|
||||
```
|
||||
|
||||
6. If you make any changes in the CLI/Core/SDK, you'll need to `CTRL+C` to exit the `dev` command and restart it to pickup changes. Any changes to the files inside of the `v3-catalog/src/trigger` dir will automatically be rebuilt by the `dev` command.
|
||||
6. If you make any changes in the CLI/Core/SDK, you'll need to `CTRL+C` to exit the `dev` command and restart it to pickup changes. Any changes to the files inside of the `hello-world/src/trigger` dir will automatically be rebuilt by the `dev` command.
|
||||
|
||||
7. Navigate to the `v3-catalog` project in your local dashboard at localhost:3030 and you should see the list of tasks.
|
||||
7. Navigate to the `hello-world` project in your local dashboard at localhost:3030 and you should see the list of tasks.
|
||||
|
||||
8. Go to the "Test" page in the sidebar and select a task. Then enter a payload and click "Run test". You can tell what the payloads should be by looking at the relevant task file inside the `/references/v3-catalog/src/trigger` folder. Many of them accept an empty payload.
|
||||
8. Go to the "Test" page in the sidebar and select a task. Then enter a payload and click "Run test". You can tell what the payloads should be by looking at the relevant task file inside the `/references/hello-world/src/trigger` folder. Many of them accept an empty payload.
|
||||
|
||||
9. Feel free to add additional files in `v3-catalog/src/trigger` to test out specific aspects of the system, or add in edge cases.
|
||||
|
||||
## Running end-to-end webapp tests (deprecated)
|
||||
|
||||
To run the end-to-end tests, follow the steps below:
|
||||
|
||||
1. Set up environment variables (copy example envs into the correct place)
|
||||
|
||||
```sh
|
||||
cp ./.env.example ./.env
|
||||
cp ./references/nextjs-test/.env.example ./references/nextjs-test/.env.local
|
||||
```
|
||||
|
||||
2. Set up dependencies
|
||||
|
||||
```sh
|
||||
# Build packages
|
||||
pnpm run build --filter @references/nextjs-test^...
|
||||
pnpm --filter @trigger.dev/database generate
|
||||
|
||||
# Move trigger-cli bin to correct place
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
# Install playwrite browsers (ONE TIME ONLY)
|
||||
npx playwright install
|
||||
```
|
||||
|
||||
3. Set up the database
|
||||
|
||||
```sh
|
||||
pnpm run docker
|
||||
pnpm run db:migrate
|
||||
pnpm run db:seed
|
||||
```
|
||||
|
||||
4. Run the end-to-end tests
|
||||
|
||||
```sh
|
||||
pnpm run test:e2e
|
||||
```
|
||||
|
||||
### Cleanup
|
||||
|
||||
The end-to-end tests use a `setup` and `teardown` script to seed the database with test data. If the test runner doesn't exit cleanly, then the database can be left in a state where the tests can't run because the `setup` script will try to create data that already exists. If this happens, you can manually delete the `users` and `organizations` from the database using prisma studio:
|
||||
|
||||
```sh
|
||||
# With the database running (i.e. pnpm run docker)
|
||||
pnpm run db:studio
|
||||
```
|
||||
9. Feel free to add additional files in `hello-world/src/trigger` to test out specific aspects of the system, or add in edge cases.
|
||||
|
||||
## Adding and running migrations
|
||||
|
||||
|
||||
@@ -1,44 +1,75 @@
|
||||
<div align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/a45d1fa2-0ae8-4a39-4409-f4f934bfae00/public">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/3f5ad4c1-c4c8-4277-b622-290e7f37bd00/public">
|
||||
<img alt="Trigger.dev logo" src="https://imagedelivery.net/3TbraffuDZ4aEf8KWOmI_w/a45d1fa2-0ae8-4a39-4409-f4f934bfae00/public">
|
||||
</picture>
|
||||
|
||||
### Open source background jobs and AI infrastructure
|
||||
|
||||
[Discord](https://trigger.dev/discord) | [Website](https://trigger.dev) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Docs](https://trigger.dev/docs)
|
||||

|
||||
|
||||
[](https://twitter.com/triggerdotdev)
|
||||
### Build and deploy fully‑managed AI agents and workflows
|
||||
|
||||
[Website](https://trigger.dev) | [Docs](https://trigger.dev/docs) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Feature requests](https://triggerdev.featurebase.app/) | [Public roadmap](https://triggerdev.featurebase.app/roadmap) | [Self-hosting](https://trigger.dev/docs/self-hosting/overview)
|
||||
|
||||
[](https://github.com/triggerdotdev/trigger.dev)
|
||||
[](https://github.com/triggerdotdev/trigger.dev/blob/main/LICENSE)
|
||||
[](https://www.npmjs.com/package/@trigger.dev/sdk)
|
||||
[](https://www.npmjs.com/package/@trigger.dev/sdk)
|
||||
|
||||
[](https://twitter.com/triggerdotdev)
|
||||
[](https://discord.gg/nkqV9xBYWy)
|
||||
[](https://github.com/triggerdotdev/trigger.dev)
|
||||
|
||||
</div>
|
||||
|
||||
## About Trigger.dev
|
||||
|
||||
Trigger.dev is an open source platform and SDK which allows you to create long-running background jobs. Write normal async code, deploy, and never hit a timeout.
|
||||
Trigger.dev is the open-source platform for building AI workflows in TypeScript. Long-running tasks with retries, queues, observability, and elastic scaling.
|
||||
|
||||
### Key features:
|
||||
## The platform designed for building AI agents
|
||||
|
||||
- JavaScript and TypeScript SDK
|
||||
- No timeouts
|
||||
- Retries (with exponential backoff)
|
||||
- Queues and concurrency controls
|
||||
- Schedules and crons
|
||||
- Full Observability; logs, live trace views, advanced filtering
|
||||
- React hooks to interact with the Trigger API from your React app
|
||||
- Pipe LLM streams straight to your users through the Realtime API
|
||||
- Trigger tasks and display the run status and metadata anywhere in your app
|
||||
- Custom alerts, get notified by email, Slack or webhooks
|
||||
- No infrastructure to manage
|
||||
- Elastic (scaling)
|
||||
- Works with your existing tech stack
|
||||
Build [AI agents](https://trigger.dev/product/ai-agents) using all the frameworks, services and LLMs you're used to, deploy them to Trigger.dev and get durable, long-running tasks with retries, queues, observability, and elastic scaling out of the box.
|
||||
|
||||
## In your codebase
|
||||
- **Long-running without timeouts**: Execute your tasks with absolutely no timeouts, unlike AWS Lambda, Vercel, and other serverless platforms.
|
||||
|
||||
- **Durability, retries & queues**: Build rock solid agents and AI applications using our durable tasks, retries, queues and idempotency.
|
||||
|
||||
- **True runtime freedom**: Customize your deployed tasks with system packages – run browsers, Python scripts, FFmpeg and more.
|
||||
|
||||
- **Human-in-the-loop**: Programmatically pause your tasks until a human can approve, reject or give feedback.
|
||||
|
||||
- **Realtime apps & streaming**: Move your background jobs to the foreground by subscribing to runs or streaming AI responses to your app.
|
||||
|
||||
- **Observability & monitoring**: Each run has full tracing and logs. Configure error alerts to catch bugs fast.
|
||||
|
||||
## Key features:
|
||||
|
||||
- **[JavaScript and TypeScript SDK](https://trigger.dev/docs/tasks/overview)** - Build background tasks using familiar programming models
|
||||
- **[Long-running tasks](https://trigger.dev/docs/runs/max-duration)** - Handle resource-heavy tasks without timeouts
|
||||
- **[Durable cron schedules](https://trigger.dev/docs/tasks/scheduled#scheduled-tasks-cron)** - Create and attach recurring schedules of up to a year
|
||||
- **[Trigger.dev Realtime](https://trigger.dev/docs/realtime/overview)** - Trigger, subscribe to, and get real-time updates for runs, with LLM streaming support
|
||||
- **[Build extensions](https://trigger.dev/docs/config/extensions/overview#build-extensions)** - Hook directly into the build system and customize the build process. Run Python scripts, FFmpeg, browsers, and more.
|
||||
- **[React hooks](https://trigger.dev/docs/frontend/react-hooks#react-hooks)** - Interact with the Trigger.dev API on your frontend using our React hooks package
|
||||
- **[Batch triggering](https://trigger.dev/docs/triggering#tasks-batchtrigger)** - Use batchTrigger() to initiate multiple runs of a task with custom payloads and options
|
||||
- **[Structured inputs / outputs](https://trigger.dev/docs/tasks/schemaTask#schematask)** - Define precise data schemas for your tasks with runtime payload validation
|
||||
- **[Waits](https://trigger.dev/docs/wait)** - Add waits to your tasks to pause execution for a specified duration
|
||||
- **[Preview branches](https://trigger.dev/docs/deployment/preview-branches)** - Create isolated environments for testing and development. Integrates with Vercel and git workflows
|
||||
- **[Waitpoints](https://trigger.dev/docs/wait-for-token#wait-for-token)** - Add human-in-the-loop judgment at critical decision points without disrupting workflow
|
||||
- **[Concurrency & queues](https://trigger.dev/docs/queue-concurrency#concurrency-and-queues)** - Set concurrency rules to manage how multiple tasks execute
|
||||
- **[Multiple environments](https://trigger.dev/docs/how-it-works#dev-mode)** - Support for DEV, PREVIEW, STAGING, and PROD environments
|
||||
- **[No infrastructure to manage](https://trigger.dev/docs/how-it-works#trigger-dev-architecture)** - Auto-scaling infrastructure that eliminates timeouts and server management
|
||||
- **[Automatic retries](https://trigger.dev/docs/errors-retrying)** - If your task encounters an uncaught error, we automatically attempt to run it again
|
||||
- **[Checkpointing](https://trigger.dev/docs/how-it-works#the-checkpoint-resume-system)** - Tasks are inherently durable, thanks to our checkpointing feature
|
||||
- **[Versioning](https://trigger.dev/docs/versioning)** - Atomic versioning allows you to deploy new versions without affecting running tasks
|
||||
- **[Machines](https://trigger.dev/docs/machines)** - Configure the number of vCPUs and GBs of RAM you want the task to use
|
||||
- **[Observability & monitoring](https://trigger.dev/product/observability-and-monitoring)** - Monitor every aspect of your tasks' performance with comprehensive logging and visualization tools
|
||||
- **[Logging & tracing](https://trigger.dev/docs/logging)** - Comprehensive logging and tracing for all your tasks
|
||||
- **[Tags](https://trigger.dev/docs/tags#tags)** - Attach up to ten tags to each run, allowing you to filter via the dashboard, realtime, and the SDK
|
||||
- **[Run metadata](https://trigger.dev/docs/runs/metadata#run-metadata)** - Attach metadata to runs which updates as the run progresses and is available to use in your frontend for live updates
|
||||
- **[Bulk actions](https://trigger.dev/docs/bulk-actions)** - Perform actions on multiple runs simultaneously, including replaying and cancelling
|
||||
- **[Real-time alerts](https://trigger.dev/docs/troubleshooting-alerts#alerts)** - Choose your preferred notification method for run failures and deployments
|
||||
|
||||
## Write tasks in your codebase
|
||||
|
||||
Create tasks where they belong: in your codebase. Version control, localhost, test and review like you're already used to.
|
||||
|
||||
```ts
|
||||
import { task } from "@trigger.dev/sdk/v3";
|
||||
import { task } from "@trigger.dev/sdk";
|
||||
|
||||
//1. You need to export each task
|
||||
export const helloWorld = task({
|
||||
@@ -58,13 +89,13 @@ Use our SDK to write tasks in your codebase. There's no infrastructure to manage
|
||||
|
||||
## Environments
|
||||
|
||||
We support `Development`, `Staging`, and `Production` environments, allowing you to test your tasks before deploying them to production.
|
||||
We support `Development`, `Staging`, `Preview`, and `Production` environments, allowing you to test your tasks before deploying them to production.
|
||||
|
||||
## Full visibility of every job run
|
||||
|
||||
View every task in every run so you can tell exactly what happened. We provide a full trace view of every task run so you can see what happened at every step.
|
||||
|
||||

|
||||

|
||||
|
||||
# Getting started
|
||||
|
||||
@@ -73,14 +104,19 @@ The quickest way to get started is to create an account and project in our [web
|
||||
### Useful links:
|
||||
|
||||
- [Quick start](https://trigger.dev/docs/quick-start) - get up and running in minutes
|
||||
- [How it works](https://trigger.dev/docs/v3/how-it-works) - understand how Trigger.dev works under the hood
|
||||
- [How it works](https://trigger.dev/docs/how-it-works) - understand how Trigger.dev works under the hood
|
||||
- [Guides and examples](https://trigger.dev/docs/guides/introduction) - walk-through guides and code examples for popular frameworks and use cases
|
||||
|
||||
## Self-hosting
|
||||
|
||||
If you prefer to self-host Trigger.dev, you can follow our [self-hosting guide](https://trigger.dev/docs/v3/open-source-self-hosting#overview).
|
||||
If you prefer to self-host Trigger.dev, you can follow our [self-hosting guides](https://trigger.dev/docs/self-hosting/overview):
|
||||
|
||||
We also have a dedicated self-hosting channel in our [Discord server](https://trigger.dev/discord) for support.
|
||||
- [Docker self-hosting guide](https://trigger.dev/docs/self-hosting/docker) - use Docker Compose to spin up a Trigger.dev instance
|
||||
- [Kubernetes self-hosting guide](https://trigger.dev/docs/self-hosting/kubernetes) - use our official Helm chart to deploy Trigger.dev to your Kubernetes cluster
|
||||
|
||||
## Support and community
|
||||
|
||||
We have a large active community in our official [Discord server](https://trigger.dev/discord) for support, including a dedicated channel for self-hosting.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-ecr": "^3.839.0",
|
||||
"@kubernetes/client-node": "^1.0.0",
|
||||
"@trigger.dev/core": "workspace:*",
|
||||
"dockerode": "^4.0.6",
|
||||
"prom-client": "^15.1.0",
|
||||
"socket.io": "4.7.4",
|
||||
"std-env": "^3.8.0",
|
||||
"zod": "3.23.8"
|
||||
"zod": "3.25.76"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/dockerode": "^3.3.33"
|
||||
|
||||
@@ -15,7 +15,7 @@ const Env = z.object({
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT: z.string().url(), // set on the runners
|
||||
|
||||
// Workload API settings (coordinator mode) - the workload API is what the run controller connects to
|
||||
TRIGGER_WORKLOAD_API_ENABLED: BoolEnv.default("true"),
|
||||
TRIGGER_WORKLOAD_API_ENABLED: BoolEnv.default(true),
|
||||
TRIGGER_WORKLOAD_API_PROTOCOL: z
|
||||
.string()
|
||||
.transform((s) => z.enum(["http", "https"]).parse(s.toLowerCase()))
|
||||
@@ -32,7 +32,7 @@ const Env = z.object({
|
||||
RUNNER_PRETTY_LOGS: BoolEnv.default(false),
|
||||
|
||||
// Dequeue settings (provider mode)
|
||||
TRIGGER_DEQUEUE_ENABLED: BoolEnv.default("true"),
|
||||
TRIGGER_DEQUEUE_ENABLED: BoolEnv.default(true),
|
||||
TRIGGER_DEQUEUE_INTERVAL_MS: z.coerce.number().int().default(250),
|
||||
TRIGGER_DEQUEUE_IDLE_INTERVAL_MS: z.coerce.number().int().default(1000),
|
||||
TRIGGER_DEQUEUE_MAX_RUN_COUNT: z.coerce.number().int().default(10),
|
||||
@@ -76,6 +76,11 @@ const Env = z.object({
|
||||
KUBERNETES_IMAGE_PULL_SECRETS: z.string().optional(), // csv
|
||||
KUBERNETES_EPHEMERAL_STORAGE_SIZE_LIMIT: z.string().default("10Gi"),
|
||||
KUBERNETES_EPHEMERAL_STORAGE_SIZE_REQUEST: z.string().default("2Gi"),
|
||||
KUBERNETES_STRIP_IMAGE_DIGEST: BoolEnv.default(false),
|
||||
|
||||
// Placement tags settings
|
||||
PLACEMENT_TAGS_ENABLED: BoolEnv.default(false),
|
||||
PLACEMENT_TAGS_PREFIX: z.string().default("node.cluster.x-k8s.io"),
|
||||
|
||||
// Metrics
|
||||
METRICS_ENABLED: BoolEnv.default(true),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SimpleStructuredLogger } from "@trigger.dev/core/v3/utils/structuredLog
|
||||
|
||||
const logger = new SimpleStructuredLogger("env-util");
|
||||
|
||||
export const BoolEnv = z.preprocess((val) => {
|
||||
const baseBoolEnv = z.preprocess((val) => {
|
||||
if (typeof val !== "string") {
|
||||
return val;
|
||||
}
|
||||
@@ -11,6 +11,11 @@ export const BoolEnv = z.preprocess((val) => {
|
||||
return ["true", "1"].includes(val.toLowerCase().trim());
|
||||
}, z.boolean());
|
||||
|
||||
// Create a type-safe version that only accepts boolean defaults
|
||||
export const BoolEnv = baseBoolEnv as Omit<typeof baseBoolEnv, "default"> & {
|
||||
default: (value: boolean) => z.ZodDefault<typeof baseBoolEnv>;
|
||||
};
|
||||
|
||||
export const AdditionalEnvVars = z.preprocess((val) => {
|
||||
if (typeof val !== "string") {
|
||||
return val;
|
||||
|
||||
@@ -247,6 +247,7 @@ class ManagedSupervisor {
|
||||
nextAttemptNumber: message.run.attemptNumber,
|
||||
snapshotId: message.snapshot.id,
|
||||
snapshotFriendlyId: message.snapshot.friendlyId,
|
||||
placementTags: message.placementTags,
|
||||
});
|
||||
|
||||
// Disabled for now
|
||||
|
||||
@@ -8,14 +8,16 @@ import { env } from "../env.js";
|
||||
import { getDockerHostDomain, getRunnerId, normalizeDockerHostUrl } from "../util.js";
|
||||
import Docker from "dockerode";
|
||||
import { tryCatch } from "@trigger.dev/core";
|
||||
import { ECRAuthService } from "./ecrAuth.js";
|
||||
|
||||
export class DockerWorkloadManager implements WorkloadManager {
|
||||
private readonly logger = new SimpleStructuredLogger("docker-workload-manager");
|
||||
private readonly docker: Docker;
|
||||
|
||||
private readonly runnerNetworks: string[];
|
||||
private readonly auth?: Docker.AuthConfig;
|
||||
private readonly staticAuth?: Docker.AuthConfig;
|
||||
private readonly platformOverride?: string;
|
||||
private readonly ecrAuthService?: ECRAuthService;
|
||||
|
||||
constructor(private opts: WorkloadManagerOptions) {
|
||||
this.docker = new Docker({
|
||||
@@ -44,13 +46,18 @@ export class DockerWorkloadManager implements WorkloadManager {
|
||||
url: env.DOCKER_REGISTRY_URL,
|
||||
});
|
||||
|
||||
this.auth = {
|
||||
this.staticAuth = {
|
||||
username: env.DOCKER_REGISTRY_USERNAME,
|
||||
password: env.DOCKER_REGISTRY_PASSWORD,
|
||||
serveraddress: env.DOCKER_REGISTRY_URL,
|
||||
};
|
||||
} else if (ECRAuthService.hasAWSCredentials()) {
|
||||
this.logger.info("🐋 AWS credentials found, initializing ECR auth service");
|
||||
this.ecrAuthService = new ECRAuthService();
|
||||
} else {
|
||||
this.logger.warn("🐋 No Docker registry credentials provided, skipping auth");
|
||||
this.logger.warn(
|
||||
"🐋 No Docker registry credentials or AWS credentials provided, skipping auth"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,9 +167,12 @@ export class DockerWorkloadManager implements WorkloadManager {
|
||||
imageArchitecture: inspectResult?.Architecture,
|
||||
});
|
||||
|
||||
// Get auth config (static or ECR)
|
||||
const authConfig = await this.getAuthConfig();
|
||||
|
||||
// Ensure the image is present
|
||||
const [createImageError, imageResponseReader] = await tryCatch(
|
||||
this.docker.createImage(this.auth, {
|
||||
this.docker.createImage(authConfig, {
|
||||
fromImage: imageRef,
|
||||
...(this.platformOverride ? { platform: this.platformOverride } : {}),
|
||||
})
|
||||
@@ -216,6 +226,26 @@ export class DockerWorkloadManager implements WorkloadManager {
|
||||
logger.debug("create succeeded", { startResult, containerId: container.id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication config for Docker operations
|
||||
* Uses static credentials if available, otherwise attempts ECR auth
|
||||
*/
|
||||
private async getAuthConfig(): Promise<Docker.AuthConfig | undefined> {
|
||||
// Use static credentials if available
|
||||
if (this.staticAuth) {
|
||||
return this.staticAuth;
|
||||
}
|
||||
|
||||
// Use ECR auth if service is available
|
||||
if (this.ecrAuthService) {
|
||||
const ecrAuth = await this.ecrAuthService.getAuthConfig();
|
||||
return ecrAuth || undefined;
|
||||
}
|
||||
|
||||
// No auth available
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async attachContainerToNetworks({
|
||||
containerId,
|
||||
networkNames,
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
import { ECRClient, GetAuthorizationTokenCommand } from "@aws-sdk/client-ecr";
|
||||
import { SimpleStructuredLogger } from "@trigger.dev/core/v3/utils/structuredLogger";
|
||||
import { tryCatch } from "@trigger.dev/core";
|
||||
import Docker from "dockerode";
|
||||
|
||||
interface ECRTokenCache {
|
||||
token: string;
|
||||
username: string;
|
||||
serverAddress: string;
|
||||
expiresAt: Date;
|
||||
}
|
||||
|
||||
export class ECRAuthService {
|
||||
private readonly logger = new SimpleStructuredLogger("ecr-auth-service");
|
||||
private readonly ecrClient: ECRClient;
|
||||
private tokenCache: ECRTokenCache | null = null;
|
||||
|
||||
constructor() {
|
||||
this.ecrClient = new ECRClient();
|
||||
|
||||
this.logger.info("🔐 ECR Auth Service initialized", {
|
||||
region: this.ecrClient.config.region,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we have AWS credentials configured
|
||||
*/
|
||||
static hasAWSCredentials(): boolean {
|
||||
if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
process.env.AWS_PROFILE ||
|
||||
process.env.AWS_ROLE_ARN ||
|
||||
process.env.AWS_WEB_IDENTITY_TOKEN_FILE
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current token is still valid with a 10-minute buffer
|
||||
*/
|
||||
private isTokenValid(): boolean {
|
||||
if (!this.tokenCache) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const bufferMs = 10 * 60 * 1000; // 10 minute buffer before expiration
|
||||
return now < new Date(this.tokenCache.expiresAt.getTime() - bufferMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh ECR authorization token from AWS
|
||||
*/
|
||||
private async fetchNewToken(): Promise<ECRTokenCache | null> {
|
||||
const [error, response] = await tryCatch(
|
||||
this.ecrClient.send(new GetAuthorizationTokenCommand({}))
|
||||
);
|
||||
|
||||
if (error) {
|
||||
this.logger.error("Failed to get ECR authorization token", { error });
|
||||
return null;
|
||||
}
|
||||
|
||||
const authData = response.authorizationData?.[0];
|
||||
if (!authData?.authorizationToken || !authData.proxyEndpoint) {
|
||||
this.logger.error("Invalid ECR authorization response", { authData });
|
||||
return null;
|
||||
}
|
||||
|
||||
// Decode the base64 token to get username:password
|
||||
const decoded = Buffer.from(authData.authorizationToken, "base64").toString("utf-8");
|
||||
const [username, password] = decoded.split(":", 2);
|
||||
|
||||
if (!username || !password) {
|
||||
this.logger.error("Failed to parse ECR authorization token");
|
||||
return null;
|
||||
}
|
||||
|
||||
const expiresAt = authData.expiresAt || new Date(Date.now() + 12 * 60 * 60 * 1000); // Default 12 hours
|
||||
|
||||
const tokenCache: ECRTokenCache = {
|
||||
token: password,
|
||||
username,
|
||||
serverAddress: authData.proxyEndpoint,
|
||||
expiresAt,
|
||||
};
|
||||
|
||||
this.logger.info("🔐 Successfully fetched ECR token", {
|
||||
username,
|
||||
serverAddress: authData.proxyEndpoint,
|
||||
expiresAt: expiresAt.toISOString(),
|
||||
});
|
||||
|
||||
return tokenCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ECR auth config for Docker operations
|
||||
* Returns cached token if valid, otherwise fetches a new one
|
||||
*/
|
||||
async getAuthConfig(): Promise<Docker.AuthConfig | null> {
|
||||
// Check if cached token is still valid
|
||||
if (this.isTokenValid()) {
|
||||
this.logger.debug("Using cached ECR token");
|
||||
return {
|
||||
username: this.tokenCache!.username,
|
||||
password: this.tokenCache!.token,
|
||||
serveraddress: this.tokenCache!.serverAddress,
|
||||
};
|
||||
}
|
||||
|
||||
// Fetch new token
|
||||
this.logger.info("Fetching new ECR authorization token");
|
||||
const newToken = await this.fetchNewToken();
|
||||
|
||||
if (!newToken) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cache the new token
|
||||
this.tokenCache = newToken;
|
||||
|
||||
return {
|
||||
username: newToken.username,
|
||||
password: newToken.token,
|
||||
serveraddress: newToken.serverAddress,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached token (useful for testing or forcing refresh)
|
||||
*/
|
||||
clearCache(): void {
|
||||
this.tokenCache = null;
|
||||
this.logger.debug("ECR token cache cleared");
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,8 @@ import {
|
||||
type WorkloadManagerCreateOptions,
|
||||
type WorkloadManagerOptions,
|
||||
} from "./types.js";
|
||||
import type { EnvironmentType, MachinePreset } from "@trigger.dev/core/v3";
|
||||
import type { EnvironmentType, MachinePreset, PlacementTag } from "@trigger.dev/core/v3";
|
||||
import { PlacementTagProcessor } from "@trigger.dev/core/v3/serverOnly";
|
||||
import { env } from "../env.js";
|
||||
import { type K8sApi, createK8sApi, type k8s } from "../clients/kubernetes.js";
|
||||
import { getRunnerId } from "../util.js";
|
||||
@@ -17,9 +18,14 @@ export class KubernetesWorkloadManager implements WorkloadManager {
|
||||
private readonly logger = new SimpleStructuredLogger("kubernetes-workload-provider");
|
||||
private k8s: K8sApi;
|
||||
private namespace = env.KUBERNETES_NAMESPACE;
|
||||
private placementTagProcessor: PlacementTagProcessor;
|
||||
|
||||
constructor(private opts: WorkloadManagerOptions) {
|
||||
this.k8s = createK8sApi();
|
||||
this.placementTagProcessor = new PlacementTagProcessor({
|
||||
enabled: env.PLACEMENT_TAGS_ENABLED,
|
||||
prefix: env.PLACEMENT_TAGS_PREFIX,
|
||||
});
|
||||
|
||||
if (opts.workloadApiDomain) {
|
||||
this.logger.warn("[KubernetesWorkloadManager] ⚠️ Custom workload API domain", {
|
||||
@@ -28,6 +34,35 @@ export class KubernetesWorkloadManager implements WorkloadManager {
|
||||
}
|
||||
}
|
||||
|
||||
private addPlacementTags(
|
||||
podSpec: Omit<k8s.V1PodSpec, "containers">,
|
||||
placementTags?: PlacementTag[]
|
||||
): Omit<k8s.V1PodSpec, "containers"> {
|
||||
const nodeSelector = this.placementTagProcessor.convertToNodeSelector(
|
||||
placementTags,
|
||||
podSpec.nodeSelector
|
||||
);
|
||||
|
||||
return {
|
||||
...podSpec,
|
||||
nodeSelector,
|
||||
};
|
||||
}
|
||||
|
||||
private stripImageDigest(imageRef: string): string {
|
||||
if (!env.KUBERNETES_STRIP_IMAGE_DIGEST) {
|
||||
return imageRef;
|
||||
}
|
||||
|
||||
const atIndex = imageRef.lastIndexOf("@");
|
||||
|
||||
if (atIndex === -1) {
|
||||
return imageRef;
|
||||
}
|
||||
|
||||
return imageRef.substring(0, atIndex);
|
||||
}
|
||||
|
||||
async create(opts: WorkloadManagerCreateOptions) {
|
||||
this.logger.log("[KubernetesWorkloadManager] Creating container", { opts });
|
||||
|
||||
@@ -48,12 +83,12 @@ export class KubernetesWorkloadManager implements WorkloadManager {
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
...this.#defaultPodSpec,
|
||||
...this.addPlacementTags(this.#defaultPodSpec, opts.placementTags),
|
||||
terminationGracePeriodSeconds: 60 * 60,
|
||||
containers: [
|
||||
{
|
||||
name: "run-controller",
|
||||
image: opts.image,
|
||||
image: this.stripImageDigest(opts.image),
|
||||
ports: [
|
||||
{
|
||||
containerPort: 8000,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user