Skip to content

Commit 3489a09

Browse files
authored
Merge pull request MemPalace#135 from igorls/fix/chromadb-singleton
perf: cache ChromaDB PersistentClient instead of re-instantiating per call
2 parents 71736a3 + 47696be commit 3489a09

4 files changed

Lines changed: 36 additions & 9 deletions

File tree

mempalace/mcp_server.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,21 @@
3939
_config = MempalaceConfig()
4040

4141

42+
_client_cache = None
43+
_collection_cache = None
44+
45+
4246
def _get_collection(create=False):
43-
"""Return the ChromaDB collection, or None on failure."""
47+
"""Return the ChromaDB collection, caching the client between calls."""
48+
global _client_cache, _collection_cache
4449
try:
45-
client = chromadb.PersistentClient(path=_config.palace_path)
50+
if _client_cache is None:
51+
_client_cache = chromadb.PersistentClient(path=_config.palace_path)
4652
if create:
47-
return client.get_or_create_collection(_config.collection_name)
48-
return client.get_collection(_config.collection_name)
53+
_collection_cache = _client_cache.get_or_create_collection(_config.collection_name)
54+
elif _collection_cache is None:
55+
_collection_cache = _client_cache.get_collection(_config.collection_name)
56+
return _collection_cache
4957
except Exception:
5058
return None
5159

tests/conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@
3434
from mempalace.knowledge_graph import KnowledgeGraph # noqa: E402
3535

3636

37+
@pytest.fixture(autouse=True)
38+
def _reset_mcp_cache():
39+
"""Reset the MCP server's cached ChromaDB client/collection between tests."""
40+
41+
def _clear_cache():
42+
try:
43+
from mempalace import mcp_server
44+
45+
mcp_server._client_cache = None
46+
mcp_server._collection_cache = None
47+
except (ImportError, AttributeError):
48+
pass
49+
50+
_clear_cache()
51+
yield
52+
_clear_cache()
53+
54+
3755
@pytest.fixture(scope="session", autouse=True)
3856
def _isolate_home():
3957
"""Ensure HOME points to a temp dir for the entire test session.

tests/test_mcp_server.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,10 @@ def test_get_taxonomy(self, monkeypatch, config, palace_path, seeded_collection,
151151
assert result["taxonomy"]["project"]["frontend"] == 1
152152
assert result["taxonomy"]["notes"]["planning"] == 1
153153

154-
def test_no_palace_returns_error(self, monkeypatch, config, kg):
155-
config._file_config["palace_path"] = "/nonexistent/path"
156-
_patch_mcp_server(monkeypatch, config, "/nonexistent/path", kg)
154+
def test_no_palace_returns_error(self, monkeypatch, config, kg, tmp_path):
155+
missing = str(tmp_path / "missing")
156+
config._file_config["palace_path"] = missing
157+
_patch_mcp_server(monkeypatch, config, missing, kg)
157158
from mempalace.mcp_server import tool_status
158159

159160
result = tool_status()

tests/test_searcher.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def test_n_results_limit(self, palace_path, seeded_collection):
3030
result = search_memories("code", palace_path, n_results=2)
3131
assert len(result["results"]) <= 2
3232

33-
def test_no_palace_returns_error(self):
34-
result = search_memories("anything", "/nonexistent/path")
33+
def test_no_palace_returns_error(self, tmp_path):
34+
result = search_memories("anything", str(tmp_path / "missing"))
3535
assert "error" in result
3636

3737
def test_result_fields(self, palace_path, seeded_collection):

0 commit comments

Comments
 (0)