perf(webui/session-load-latency) tier3c: fix scene comparison direction in cache fast-path

The fast-path scene comparison in _cached_session_lags_disk had two bugs
flagged by nesquena-hermes review:

1. Direction: used symmetric != instead of directional subset check.
   When the cache had scene keys that disk lacked (cache-ahead), the old
   code force-reloaded from disk, silently dropping un-persisted scene
   data. Now mirrors master: reload only when disk is strictly ahead
   (disk_keys.issubset(cached_keys)). The 'not disk_scenes' early-return
   is also removed — empty disk scenes means disk is not ahead, so keep
   the cache.

2. Key filtering mismatch: used raw set(disk_scenes.keys()) instead of
   _anchor_scene_record_keys() helper which filters to truthy keys with
   dict values. Now filters disk keys the same way as master, and uses
   _anchor_scene_record_keys(cached) for the cached session object.

Also updated the tier3b content-prefix docstring to clarify it is a
best-effort backstop limited to the first 128 chars, not a full
integrity check.
This commit is contained in:
Konstantin M
2026-07-09 02:21:25 +00:00
parent aa78590164
commit b5c0447a4a
2 changed files with 34 additions and 19 deletions
+27 -19
View File
@@ -3133,25 +3133,33 @@ def _cached_session_lags_disk(cached) -> bool:
disk_scenes = disk_meta_quick.get('anchor_activity_scenes') or {}
if not isinstance(disk_scenes, dict):
disk_scenes = {}
if not disk_scenes or set(disk_scenes.keys()) != set(cached_scenes.keys()):
# Scene key set differs — disk has been updated with new
# keys the cache hasn't seen.
return True
# Same key set: check the latest updated_at timestamp.
def _max_updated(records):
latest = 0.0
for record in records.values():
if not isinstance(record, dict):
continue
try:
ua = float(record.get('updated_at') or 0)
except (TypeError, ValueError):
ua = 0.0
if ua > latest:
latest = ua
return latest
if _max_updated(disk_scenes) > _max_updated(cached_scenes):
return True
if disk_scenes:
# Directional: only reload when disk is strictly ahead
# of cache. Mirror master's subset comparison — cache
# that is ahead of disk must NOT force a reload, or
# un-persisted scene data is silently dropped.
disk_keys = {str(key) for key, value in disk_scenes.items()
if key and isinstance(value, dict)}
cached_keys = _anchor_scene_record_keys(cached)
if disk_keys and not disk_keys.issubset(cached_keys):
return True
# Same key set (or disk is subset): check the latest
# updated_at timestamp.
def _max_updated(records):
latest = 0.0
for record in records.values():
if not isinstance(record, dict):
continue
try:
ua = float(record.get('updated_at') or 0)
except (TypeError, ValueError):
ua = 0.0
if ua > latest:
latest = ua
return latest
if _max_updated(disk_scenes) > _anchor_scene_records_updated_at(cached):
return True
# disk has no scenes, cache does -> cache is ahead; keep it.
else:
# Cached session has no scene records. Check if disk has gained
# the first scene record — without this the fast-path would miss
+7
View File
@@ -6333,6 +6333,13 @@ def _read_profile_config_cached(profile_name: str, cfg_path: str) -> dict | None
in-place rewrites where inode+mtime+size are identical on coarse
filesystems most editors use atomic-rename (new inode), but tools
like sed -i or file.write() in-place can keep the same inode.
NOTE: This is a best-effort backstop, not a full integrity check.
Edits that change bytes only after the first 128 characters while
keeping inode+mtime+size identical are not detected until the TTL
expires. This trade-off is acceptable because the TTL is only 60s
and the common case (atomic-rename editors) is fully handled by
the inode key component.
"""
try:
st = os.stat(cfg_path)