fix(backend): wait for in-flight account deletion retry before mongo stop - #3444
Merged
Merged
Conversation
…stop Graceful shutdown cleared the retry interval but never awaited a cycle already in flight, so mongoService.stop() could tear down the client mid-query and the interval callback's pendingAccountDeletion access threw "did you forget to call \`start\`?" (PostHog issue, staging, single occurrence).
Co-authored-by: Tyler Dane <tyler-dane@users.noreply.github.com>
Contributor
|
Still relevant: the shutdown race is present on current |
tyler-dane
enabled auto-merge
September 7, 2026 20:02
Contributor
|
The new regression test ( |
Closed
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.
Fixes #3442
What and why
PostHog error tracking caught a single staging occurrence of
Could not retry pending account deletions did you forget to call \start`?, thrown fromMongoService#accessInternalCollectionProps(mongo.service.ts:144) viaUserService.retryPendingAccountDeletions(user.service.ts:354, thependingSyncPurge` query).Root cause:
gracefulShutdowninapp.tscallsuserService.stopAccountDeletionRetries()(which onlyclearIntervals) beforemongoService.stop().clearIntervalstops future firings, but a retry cycle already in flight from the previous interval tick keeps running as a detachedvoid ...catch(...)promise. If shutdown lands mid-cycle,mongoService.stop()clears#internalClientwhile that cycle is still awaiting apendingAccountDeletionquery, so the next collection-getter access throws "did you forget to callstart?". This matches the observed stack trace exactly (first query in the cycle succeeded, the second one at line 354 hit the now-undefined client) and the event only occurred onstaging, consistent with a deploy/restart race rather than steady-state traffic.Fix: track the in-flight retry cycle's promise on
UserServiceand makestopAccountDeletionRetriesasync, awaiting that promise (each cycle already catches and logs its own errors) before returning.app.tsnow awaits it ingracefulShutdown, somongoService.stop()never runs while a retry cycle is still using the client.Verify
684 pass, 1 skip, 0 fail, 1643 expect() calls. Ran 685 tests across 74 files.
Selected packages: backend
Checks run: test:backend, type-check, lint, knip
Checks skipped: (none)
VERDICT: PASS
New regression test (
account deletion retry lifecycleinuser.service.db.test.ts) fails on the pre-fix code (stopAccountDeletionRetriesreturnedvoid, so nothing to.then()on) and passes with the fix.Independent review
Self-reviewed only; this PR was opened by the error-autofix pipeline (mode: merge). No second human/AI reviewer yet.
Test plan
retryPendingAccountDeletionsto stay in flight, starts the retry timer, and assertsstopAccountDeletionRetries()doesn't resolve until the cycle finishes)user.service.ts/app.tsand passes with the fixbun run verify --strictis green