fix: eliminate book-slug cache stampede that OOM-crashed search (v5.2.0)#13
Merged
Conversation
Enhancing search/recent/list results resolved a book slug per item via
getBookSlug. The cache check-then-set was not atomic across the Promise.all
batch, so results sharing a book all missed the cache simultaneously and
fanned out one concurrent GET /books/{id} per result. On large result sets
BookStack rate-limited the burst (429); each retry held buffers for tens of
seconds and the pending promises accumulated until the Node heap OOM-crashed
the container. There was also no HTTP timeout, so a slow/hung BookStack
response never returned.
- getBookSlug now bulk-warms the slug cache from a single /books listing
(memoized), turning the per-result N+1 into +1; gaps fall back to an
in-flight-deduped lazy fetch so a batch cannot stampede.
- axios gets a configurable timeout (default 30s, BOOKSTACK_TIMEOUT_MS) so a
hung request aborts cleanly instead of hanging until the client gives up.
Bumps version to 5.2.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Problem
The deployed connector was OOM-crashing. Swarm logs showed hundreds of concurrent
BookStack rate limited (429); retry N/5 in 44000msfollowed byFATAL ERROR: Reached heap limit — JavaScript heap out of memory.Root cause (cache stampede cascade): Enhancing search / recent-changes / list results resolves a book slug per item via
getBookSlug. The cache check-then-set is not atomic across thePromise.allbatch, so results sharing a book all miss the cache at once and fan out one concurrentGET /books/{id}per result (reproduced: 50 same-book results → 50 requests). BookStack 429s the burst; each retry holds buffers for tens of seconds in the manual backoff, the pending promises pile up, and the heap exhausts → container crash. Compounded by no HTTP timeout on the axios client, so a slow/hung/searchnever returns.Fix
getBookSlugbulk-warms the slug cache from a single/bookslisting (memoized on first use), turning the per-result N+1 into +1. Gaps (books created after the warm) fall back to an in-flight-deduped lazy fetch so a batch can't stampede.axiosnow has a configurabletimeout(default 30s,BOOKSTACK_TIMEOUT_MS) so a hung request aborts cleanly.Verification
npm run type-checkandnpm run buildclean. Bumps version to 5.2.0.🤖 Generated with Claude Code