From 919ff8d8e2e6196199625fbb397ec9a852350add Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 15 Feb 2026 22:00:54 +0000 Subject: [PATCH] Fix: Add caching for _ZvecClient._load_collection_entries The _load_collection_entries method was reading and JSON-parsing the full index file from disk on every invocation. During _PayloadEmbeddingIdentityStrategy.query, get_embedding_identities() triggers one read, and each subsequent per-identity _query_zvec() call triggers another. With K stored identities this resulted in K+1 full file reads and parses per search operation. Added file modification time based caching to avoid redundant I/O and JSON parsing. The cache is invalidated when the file's mtime changes, ensuring data consistency when the file is updated. --- src/catalog/catalog/store/vector.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/catalog/catalog/store/vector.py b/src/catalog/catalog/store/vector.py index a464568..cc8b108 100644 --- a/src/catalog/catalog/store/vector.py +++ b/src/catalog/catalog/store/vector.py @@ -53,6 +53,8 @@ class _ZvecClient: def __init__(self, index_path: Path) -> None: self._index_path = index_path.expanduser() + self._cached_entries: list[dict[str, Any]] | None = None + self._cached_mtime: float | None = None def query( self, @@ -109,12 +111,24 @@ def get_embedding_identities( return list(seen.values()) def _load_collection_entries(self, collection_name: str) -> list[dict[str, Any]]: - """Load and normalize vector entries from the configured local file.""" + """Load and normalize vector entries from the configured local file. + + Caches parsed entries and invalidates on file modification to avoid + redundant I/O and JSON parsing during multi-step search operations. + """ if not self._index_path.exists(): raise FileNotFoundError( f"Zvec index file does not exist: {self._index_path}" ) + current_mtime = self._index_path.stat().st_mtime + if ( + self._cached_entries is not None + and self._cached_mtime is not None + and self._cached_mtime == current_mtime + ): + return self._cached_entries + with self._index_path.open("r", encoding="utf-8") as handle: payload = json.load(handle) @@ -199,6 +213,8 @@ def _load_collection_entries(self, collection_name: str) -> list[dict[str, Any]] } ) + self._cached_entries = entries + self._cached_mtime = current_mtime return entries @staticmethod