The list rebuilt every card after each transcript write, and every client the SSE bus woke up missed the cache at once and ran the same full build in parallel on one GIL; FastAPI then encoded the big bodies on the event loop. Live, that pinned a core with /api/conversations at 16-80 s and even /api/health at 43 s. - _Memo: version-keyed, single-flight memo for the card list, agent runs and agents-by-conversation (cards also key on a 15 s time bucket, since a card's running/finished state reads the clock) - lru_cache on _conv_id / _parent_path_of / _is_sidechain_path: pathlib.relative_to was 0.24 ms a call, half the list's cost - MetaStore.peek no longer takes the lock (convoyed thousands of peeks per build); MetaStore.items() replaces the 1.4 MB deep copy in _build_agent_runs - @_json_in_worker: the eleven heaviest GETs return a ready JSONResponse from their worker thread instead of leaving jsonable_encoder (5-10x slower than json.dumps) to run on the event loop Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
9.9 KiB
9.9 KiB