From 1657a79649026f0cd2b16dff23f461550f7fdfa4 Mon Sep 17 00:00:00 2001 From: jp Date: Sat, 11 Apr 2026 20:15:55 -0700 Subject: [PATCH] fix: clarify cache docs, skip caching empty graphs Addresses Copilot review feedback on #661. Co-Authored-By: Claude Opus 4.6 --- mempalace/palace_graph.py | 14 ++++++++++---- tests/test_palace_graph.py | 7 ++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/mempalace/palace_graph.py b/mempalace/palace_graph.py index faeedd3..96c7c62 100644 --- a/mempalace/palace_graph.py +++ b/mempalace/palace_graph.py @@ -26,7 +26,8 @@ from .config import MempalaceConfig from .palace import get_collection as _get_palace_collection from .palace import mine_lock -# Module-level graph cache — mirrors _metadata_cache pattern in mcp_server.py +# Module-level graph cache with TTL and write-invalidation. +# Warm cache serves build_graph() in O(1); invalidate_graph_cache() clears on writes. _graph_cache_nodes = None _graph_cache_edges = None _graph_cache_time = 0.0 @@ -66,6 +67,8 @@ def build_graph(col=None, config=None): """ global _graph_cache_nodes, _graph_cache_edges, _graph_cache_time now = time.time() + # NOTE: warm cache ignores col/config args — intentional for the MCP server's + # single-palace use case. Callers switching collections must invalidate first. if _graph_cache_nodes is not None and (now - _graph_cache_time) < _GRAPH_CACHE_TTL: return _graph_cache_nodes, _graph_cache_edges @@ -124,9 +127,12 @@ def build_graph(col=None, config=None): "dates": sorted(data["dates"])[-5:] if data["dates"] else [], } - _graph_cache_nodes = nodes - _graph_cache_edges = edges - _graph_cache_time = time.time() + # Only cache non-empty graphs so new data is picked up immediately + # when the palace is first populated. + if nodes: + _graph_cache_nodes = nodes + _graph_cache_edges = edges + _graph_cache_time = time.time() return nodes, edges diff --git a/tests/test_palace_graph.py b/tests/test_palace_graph.py index 37497c1..7bc45e0 100644 --- a/tests/test_palace_graph.py +++ b/tests/test_palace_graph.py @@ -119,7 +119,12 @@ class TestBuildGraph: assert len(nodes["busy"]["dates"]) <= 5 def test_cache_returns_same_result(self): - """Second call within TTL returns cached nodes without re-scanning.""" + """Second call within TTL returns cached nodes without re-scanning. + + The cache intentionally ignores col/config args when warm — this is + correct for the MCP server's single-palace use case. Callers that + switch collections must call invalidate_graph_cache() first. + """ col = _make_fake_collection( [{"room": "auth", "wing": "wing_code", "hall": "security", "date": "2026-01-01"}] )