fix: lock the store's summary cache and cache the MCP graph build (#130) - #139
Merged
Conversation
The web UI ran sync endpoints on FastAPI's threadpool over a single shared OmiStore, so concurrent list_notes() calls mutated the summary cache while another thread iterated it -> "dictionary changed size during iteration" 500s under the 5s poll. Guard the cache with a lock. The MCP server's five graph tools each rebuilt the whole [[wikilink]] graph (a full-vault read+parse) per call; cache the build, invalidated by a cheap vault signature (count, size, newest mtime), so a burst of graph queries costs one parse and any write busts it. (The single-client stdio server's sync handlers are left on the event loop: blocking there delays only that one client's pings, not a crash, and the graph cache removes the pathological repeated-parse cost — an async refactor of the critical server is disproportionate risk for the remaining latency.) Closes #130. Co-Authored-By: Claude Fable 5 <[email protected]>
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.
Closes #130.
OmiStore, so concurrentlist_notes()calls mutated the summary cache while another thread iterated it →RuntimeError: dictionary changed size during iterationunder the 5-second poll. The cache is now guarded by a lock.[[wikilink]]graph per call. The build is now cached, invalidated by a cheap vault signature (note count, total size, newest mtime), so a burst of graph queries costs one parse and any write busts it.Scope note: the single-client stdio MCP server's sync handlers are deliberately left on the event loop. Blocking there delays only that one client's pings/cancellations (not a crash), and the graph cache removes the pathological repeated-parse cost that was the real harm — an async refactor of the critical server every session depends on is disproportionate risk for the remaining latency.
Test plan
list_notes()hammered from 8 threads raises no dict-resize error; the graph build is cached across 3 graph tools (1 build) and busted by a write (2 builds).🤖 Generated with Claude Code
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/