-
-
Notifications
You must be signed in to change notification settings - Fork 991
fix(cli-v3): ensure worker cleanup on SIGINT/SIGTERM (#2909) #2993
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
Changes from all commits
023c3fd
93aa053
8b684e1
737ad56
c97cbcc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@trigger.dev/core": patch | ||
| --- | ||
|
|
||
| Fix: ConsoleInterceptor now delegates to original console methods to preserve log chain when other interceptors (like Sentry) are present. (#2900) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@trigger.dev/cli-v3": patch | ||
| --- | ||
|
|
||
| Fix: Native build server failed with Docker Hub rate limits. Added support for checking checking `DOCKER_USERNAME` and `DOCKER_PASSWORD` in environment variables and logging into Docker Hub before building. (#2911) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@trigger.dev/cli-v3": patch | ||
| --- | ||
|
|
||
| Fix: Ignore engine checks during deployment install phase to prevent failure on build server when Node version mismatch exists. (#2913) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@trigger.dev/cli-v3": patch | ||
| --- | ||
|
|
||
| Fix: `trigger.dev dev` command left orphaned worker processes when exited via Ctrl+C (SIGINT). Added signal handlers to ensure proper cleanup of child processes and lockfiles. (#2909) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -171,22 +171,38 @@ export async function devCommand(options: DevCommandOptions) { | |
| ); | ||
| } else { | ||
| logger.log( | ||
| `${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.\n\n${ | ||
| authorization.error | ||
| `${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.\n\n${authorization.error | ||
| }` | ||
| ); | ||
| } | ||
| process.exitCode = 1; | ||
| return; | ||
| } | ||
|
|
||
| let watcher; | ||
| let devInstance: Awaited<ReturnType<typeof startDev>> | undefined; | ||
|
|
||
| const cleanup = async () => { | ||
| if (devInstance) { | ||
| await devInstance.stop(); | ||
| } | ||
| }; | ||
|
|
||
| const signalHandler = async (signal: string) => { | ||
| logger.debug(`Received ${signal}, cleaning up...`); | ||
| await cleanup(); | ||
| process.exit(0); | ||
| }; | ||
|
|
||
| try { | ||
| const devInstance = await startDev({ ...options, cwd: process.cwd(), login: authorization }); | ||
| watcher = devInstance.watcher; | ||
| process.on("SIGINT", signalHandler); | ||
| process.on("SIGTERM", signalHandler); | ||
|
|
||
| devInstance = await startDev({ ...options, cwd: process.cwd(), login: authorization }); | ||
| await devInstance.waitUntilExit(); | ||
| } finally { | ||
| await watcher?.stop(); | ||
| process.off("SIGINT", signalHandler); | ||
| process.off("SIGTERM", signalHandler); | ||
| await cleanup(); | ||
| } | ||
|
Comment on lines
+182
to
206
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's examine the dev.ts file around the lines in question
cat -n packages/cli-v3/src/commands/dev.ts | sed -n '280,310p'Repository: triggerdotdev/trigger.dev Length of output: 857 🏁 Script executed: # Let's also see the full context of the try-finally block and startDev
cat -n packages/cli-v3/src/commands/dev.ts | sed -n '170,210p'Repository: triggerdotdev/trigger.dev Length of output: 1442 🏁 Script executed: # Search for startDev function definition to understand the full lifecycle
rg -n 'const startDev|function startDev' packages/cli-v3/src/commands/dev.ts -A 30Repository: triggerdotdev/trigger.dev Length of output: 1088 🏁 Script executed: # Check if there's a watcher that might keep the process alive
rg -n 'watcher\|event loop\|setInterval\|setTimeout' packages/cli-v3/src/commands/dev.ts | head -20Repository: triggerdotdev/trigger.dev Length of output: 51 🏁 Script executed: # Search for watchConfig implementation
rg -n 'export.*watchConfig|const watchConfig|function watchConfig' packages/cli-v3/src/ -A 5 --type=tsRepository: triggerdotdev/trigger.dev Length of output: 392 🏁 Script executed: # Check what bootDevSession does
rg -n 'bootDevSession' packages/cli-v3/src/commands/dev.ts -B 2 -A 15Repository: triggerdotdev/trigger.dev Length of output: 1399 🏁 Script executed: # See if there are any imports or setup that might explain the lifecycle
head -50 packages/cli-v3/src/commands/dev.tsRepository: triggerdotdev/trigger.dev Length of output: 2316 🏁 Script executed: # Look for any existing test files or documentation that explains the expected behavior
fd -e test.ts -e spec.ts packages/cli-v3/src/commands/dev | head -5Repository: triggerdotdev/trigger.dev Length of output: 51 🏁 Script executed: # Let's examine the watchConfig implementation in config.ts to see if it sets up file watchers that keep the process alive
cat -n packages/cli-v3/src/config.ts | sed -n '62,150p'Repository: triggerdotdev/trigger.dev Length of output: 3206 🏁 Script executed: # Check the return type of watchConfig to understand what gets returned
rg -n 'return {' packages/cli-v3/src/config.ts | head -10Repository: triggerdotdev/trigger.dev Length of output: 148 🏁 Script executed: # Let's see what the watcher setup looks like - search for chokidar or file watch setup
rg -n 'chokidar\|watch\|FSWatcher' packages/cli-v3/src/config.ts -B 2 -A 2Repository: triggerdotdev/trigger.dev Length of output: 51 🏁 Script executed: # Check devSession to understand what startDevSession returns
rg -n 'export.*startDevSession|function startDevSession' packages/cli-v3/src/dev/devSession.ts -A 20 | head -40Repository: triggerdotdev/trigger.dev Length of output: 698 🏁 Script executed: # Get the full startDevSession function to see what DevSessionInstance contains and what it does
cat -n packages/cli-v3/src/dev/devSession.ts | sed -n '50,150p'Repository: triggerdotdev/trigger.dev Length of output: 3562 🏁 Script executed: # Check the DevSessionInstance type definition
rg -n 'type DevSessionInstance|interface DevSessionInstance' packages/cli-v3/src/dev/devSession.ts -A 10Repository: triggerdotdev/trigger.dev Length of output: 274 🏁 Script executed: # Let's check what startWorkerRuntime returns and if it keeps the process alive
rg -n 'startWorkerRuntime|return {' packages/cli-v3/src/dev/devSession.ts | head -20Repository: triggerdotdev/trigger.dev Length of output: 186 🏁 Script executed: # Look at the end of startDevSession to see what it returns
cat -n packages/cli-v3/src/dev/devSession.ts | tail -100Repository: triggerdotdev/trigger.dev Length of output: 3334 The The bundler is started in watch mode (line 200 of
In normal operation (without signals), the dev session would start and immediately stop, preventing the CLI from functioning. The signal handler flow ( The 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
|
|
@@ -272,7 +288,7 @@ async function startDev(options: StartDevOptions) { | |
|
|
||
| devInstance = await bootDevSession(watcher.config); | ||
|
|
||
| const waitUntilExit = async () => {}; | ||
| const waitUntilExit = async () => { }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 waitUntilExit is an empty function that immediately resolves, causing dev command to exit immediately The Click to expandBug MechanismAt const waitUntilExit = async () => { };This function returns a Promise that immediately resolves to await devInstance.waitUntilExit();The await completes instantly, then the Expected vs Actual Behavior
ImpactThe dev command ( Recommendation: The const waitUntilExit = () => new Promise<void>(() => {});Or better, create a mechanism to resolve the promise when the dev session should exit. Was this helpful? React with 👍 or 👎 to provide feedback. |
||
|
|
||
| return { | ||
| watcher, | ||
|
|
||
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.
Fix duplicated word in the changeset entry.
Minor typo (“checking checking”) in user-facing release notes.
📝 Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents