feat(workflow-executor): add graceful shutdown with in-flight step drain#1512
Merged
matthv merged 8 commits intofeat/prd-214-setup-workflow-executor-packagefrom Mar 27, 2026
Conversation
|
Coverage Impact Unable to calculate total coverage change because base branch coverage was not found. Modified Files with Diff Coverage (4)
🤖 Increase coverage with AI coding...🚦 See full report on Qlty Cloud » 🛟 Help
|
3 new issues
|
5394fc7 to
17e709a
Compare
- stop() now drains in-flight steps before closing resources - Add Runner.state getter: idle → running → draining → stopped - Add stopTimeoutMs config (default 30s) to prevent hanging on stuck steps - Convert inFlightSteps from Set to Map to track step promises - HTTP server stays up during drain for frontend access - Add Logger.info optional method for drain status messages - 7 new tests: drain, timeout, state transitions, log messages fixes PRD-241 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Public endpoint (no JWT required) that returns the Runner state:
- 200 { state: 'running' } or { state: 'draining' }
- 503 { state: 'stopped' } or { state: 'idle' }
Usable as k8s readiness probe, ECS health check, or manual curl.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bf5ca08 to
371befc
Compare
Register process signal handlers in start(), remove them in stop(). On SIGTERM or SIGINT, the runner drains in-flight steps then exits. If stop() fails, exits with code 1. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dlers - Runner is now a pure library: no HTTP server, no process signals - Factory functions (buildInMemoryExecutor/buildDatabaseExecutor) compose Runner + ExecutorHttpServer + SIGTERM/SIGINT handlers - Fix review issues: - Re-entrancy guard in stop() (idle/stopped/draining → return) - Clear drain timer when drain succeeds - Inspect Promise.allSettled results and log failures - process.exitCode instead of process.exit() - HTTP server stop wrapped in try-catch - WorkflowExecutor interface now exposes state getter Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- httpPort now required in ExecutorOptions (executor always needs HTTP) - start() rejects on stopped Runner (cannot restart after stop) - stop() uses finally block to guarantee state reaches 'stopped' - logger.info called with ?. (info is optional on Logger interface) - drainTimer initialized as undefined, cleared on success - Shared shutdown promise (concurrent callers await the same shutdown) - Safety net: force exit after 5s if event loop doesn't drain (.unref()) - HTTP server stop wrapped in try-catch (failure doesn't block drain) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents calling start() while stop() is draining, which would reinitialize the store and resume polling against closing resources. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cycle Test the composeur created by buildInMemoryExecutor: - start() calls runner.start + registers SIGTERM/SIGINT - stop() removes signals + calls runner.stop - Concurrent stop() calls share the same promise - HTTP server close failure doesn't prevent runner.stop - state getter returns runner state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ogger - Runner: test start() after stop() throws, resource cleanup failure log - DatabaseStore: test migration failure logging, close() error handling - build-run-store: test both factory functions (SQLite + in-memory) - ConsoleLogger: test info() method Coverage improvements: console-logger 67% → 100% build-run-store 33% → 100% database-store 85% → 96% runner 97% → 99% Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scra3
approved these changes
Mar 27, 2026
7142e6c
into
feat/prd-214-setup-workflow-executor-package
29 of 30 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
stop()now waits for in-flight steps to complete before closing resourcesrunner.stateexposes the lifecycle:idle → running → draining → stoppedstopTimeoutMs(default 30s) preventsstop()from hanging on stuck stepsHow it works
Test plan
fixes PRD-241
🤖 Generated with Claude Code
Note
Add graceful shutdown with in-flight step drain to workflow executor
Runnergains aRunnerState(idle→running→draining→stopped) andstop()now waits for all in-flight steps to complete before shutting down, with a configurablestopTimeoutMs(default 30s).buildInMemoryExecutorandbuildDatabaseExecutornow return aWorkflowExecutorfacade withstart(),stop(), andstate; signal handlers forSIGTERM/SIGINTare registered on start and removed on stop.GET /healthendpoint onExecutorHttpServerreturns 200 when state isrunningordraining, and 503 otherwise.ConsoleLoggerand theLoggerport gain an optionalinfo()method used to log drain progress.Runnercan no longer be restarted after reachingstoppedordrainingstate, andstart()no longer manages an HTTP server directly.Macroscope summarized ba45db9.