Skip to content

fix(server,proxy): portable REPO_ROOT + flush queued usage-worker messages on shutdown - #63

Open
doanhv wants to merge 2 commits into
snipeship:mainfrom
doanhv:fix/graceful-shutdown-test-hardcoded-repo-root
Open

fix(server,proxy): portable REPO_ROOT + flush queued usage-worker messages on shutdown#63
doanhv wants to merge 2 commits into
snipeship:mainfrom
doanhv:fix/graceful-shutdown-test-hardcoded-repo-root

Conversation

@doanhv

@doanhv doanhv commented Jul 23, 2026

Copy link
Copy Markdown

Two stacked bugs found while investigating why graceful-shutdown.integration.test.ts fails: (1) REPO_ROOT was hardcoded to the original authors local machine path, used as Bun.spawns cwd -- fails with a misleading ENOENT on any other checkout. Fixed by reusing the repos own pre-existing portable helper (test-helpers/workspace.ts). (2) After that fix, the test still failed with a different signature (exitCode=1): usage-worker.ts's terminateGracefully() wiped queuedMessages synchronously without ever trying to flush them if the worker was not ready, permanently losing pending usage/analytics-log writes on shutdown; compounded by handleWorkerMessage()'s shuttingDown early-return sitting before the ready-message branch. Fixed with a bounded wait-for-ready-then-flush before dropping (with a logged warning) whatever remains queued. Two further races were found and fixed during independent review: forceTerminate() racing an in-flight terminateGracefully() wait used to leave that promise unsettled for the full timeout then silently resolve instead of reject; and a standalone forceTerminate() could leak stale error state into a later, unrelated terminateGracefully() call. Both covered by dedicated regression tests. Test plan: graceful-shutdown.integration.test.ts passes reliably now (was deterministic failure before); 3 new usage-worker.test.ts unit tests, stable across repeated runs; full workspace typecheck clean.

DoanHV added 2 commits July 23, 2026 22:18
graceful-shutdown.integration.test.ts hardcoded
REPO_ROOT = "/Users/brain/Coding/snipeship/ccflare" (the original
author's local path, used as Bun.spawn's cwd. On any other checkout
this directory does not exist, and Bun's posix_spawn fails with a
misleading ENOENT attributed to the bun binary rather than the cwd.

Reuse the existing portable helper from ./test-helpers/workspace.ts
(REPO_ROOT computed via import.meta.dir, already used by sibling
integration tests in this same app) instead of a second, hardcoded
definition.

Note: this test still fails after this fix, but for a separate,
unrelated reason (a real bug in packages/proxy/src/usage-worker.ts's
terminateGracefully(), tracked separately) -- this commit only removes
the path-portability failure mode, confirmed by an independent review
that reproduced both the old ENOENT crash (before) and the new,
different assertion failure (after) via direct execution.
EOF
)
terminateGracefully() cleared queuedMessages synchronously and
unconditionally, even when the worker was not yet ready and those
messages had never been sent -- permanently losing pending
usage/analytics-log writes whenever shutdown raced with worker
startup. handleWorkerMessage()'s shuttingDown early-return also sat
before the ready-message branch, so a ready signal arriving during the
shutdown window was ignored, making the loss unrecoverable once
shutdown began.

terminateGracefully() now waits (bounded by readyTimeoutMs) for the
worker to become ready before flushing, only dropping (with a logged
warning) whatever is still queued afterward. handleWorkerMessage's
ready branch now unblocks that wait unconditionally, while still only
auto-flushing when not shutting down. forceTerminate() gets a
best-effort, non-blocking flush instead of an unconditional wipe.

Two further races were found and fixed during independent review:
forceTerminate() racing an in-flight terminateGracefully() wait used to
leave that promise unsettled for the full timeout and then silently
resolve instead of reject; and a standalone forceTerminate() could
leak stale error state into a later, unrelated terminateGracefully()
call. Both are covered by dedicated regression tests.

Second commit on this branch: builds on the REPO_ROOT path fix already
here, since apps/server/src/graceful-shutdown.integration.test.ts only
passes reliably once both issues are fixed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant