diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ec9144e..e8c9e085 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed +- **Profile list no longer serves stale rows after a change.** The session-load perf pass (v0.51.908) bumped the profile-list cache TTL to 60s, but profile-row mutations (default model / providers / skills / gateway config) don't invalidate that cache, so a changed profile could show stale details for up to a minute. Reverted the TTL to 4s — frequent enough that mutation-to-refresh staleness is negligible, while rapid dropdown re-opens stay cheap. Thanks @Kopamed. (#5696) - **Faster session loads on long conversations.** Opening a session with thousands of messages was taking multiple seconds because `Session.compact()` re-walked the whole message list on every response (an O(N) user-message count plus a full reverse scan for the last-message timestamp), and the slow-request watchdog didn't cover the `/api/session` path. The user-count and last-message-timestamp lookups are now bounded (a tail-window scan with an exact full-scan fallback), and slow-request instrumentation covers the session-load path so future regressions are caught. Multi-second loads on large sessions drop to sub-second. Thanks @Kopamed. (#5696, #5455) ### Internal diff --git a/api/profiles.py b/api/profiles.py index e83724b8..7f047673 100644 --- a/api/profiles.py +++ b/api/profiles.py @@ -1835,9 +1835,7 @@ def _get_profile_skills_stats(profile_dir: Path) -> tuple[int, int]: _LIST_PROFILES_CACHE: tuple[list, float] | None = None -_LIST_PROFILES_CACHE_TTL = 60.0 # seconds — bumped from 4.0 for perf(session-load-latency) Priority 4. Profile rows are static across a session load; a 4s TTL forced the os.walk + skill-tree parse on every poll. Invalidation hooks below (create/delete) clear the cache immediately on real changes. - # profiles stay near-live, long enough that rapid - # re-opens of the dropdown are free. +_LIST_PROFILES_CACHE_TTL = 4.0 # seconds. The perf(session-load-latency) pass bumped this to 60s, but that was reverted: profile-row mutations (defaults / providers / skills / gateway config) do NOT invalidate this cache, so a 60s TTL served stale profile rows for too long after such a change. 4s keeps the os.walk frequent enough that mutation→poll staleness is negligible while still making rapid dropdown re-opens free. The create/delete invalidation hooks below clear the cache immediately on those specific mutations. _LIST_PROFILES_CACHE_LOCK = threading.Lock()