diff --git a/backend/app/graph/graphiti_backend.py b/backend/app/graph/graphiti_backend.py index 8ce10f97..cbc93a18 100644 --- a/backend/app/graph/graphiti_backend.py +++ b/backend/app/graph/graphiti_backend.py @@ -521,8 +521,9 @@ class GraphitiBackend(GraphBackend): ) async def _execute_neo4j_query(self, query: str, parameters: dict = None): - """Execute a raw Cypher query against Neo4j via the sync driver in the shared event loop.""" - result = await asyncio.get_event_loop().run_in_executor( + """Execute a raw Cypher query against Neo4j via the sync driver in a thread pool.""" + loop = asyncio.get_running_loop() + result = await loop.run_in_executor( None, lambda: self._client.driver.execute_query(query, **({"parameters_": parameters} if parameters else {})) ) @@ -548,15 +549,9 @@ class GraphitiBackend(GraphBackend): """ await self._execute_neo4j_query(clone_rels_query, {"src": src_group_id, "dst": dst_group_id}) - async def delete_graph_async(self, group_id: str) -> None: - """Delete all nodes and relationships for a given group_id (async version).""" - delete_query = "MATCH (n) WHERE n.group_id = $gid DETACH DELETE n" - await self._execute_neo4j_query(delete_query, {"gid": group_id}) - def delete_graph(self, graph_id: str) -> None: - _run_async( - self._client.driver.execute_query( - "MATCH (n {group_id: $gid}) DETACH DELETE n", - params={"gid": graph_id}, - ) - ) + """Delete all nodes and relationships for a given group_id.""" + _run_async(self._execute_neo4j_query( + "MATCH (n) WHERE n.group_id = $gid DETACH DELETE n", + {"gid": graph_id}, + )) diff --git a/backend/tests/test_graph_clone.py b/backend/tests/test_graph_clone.py index 82e3802f..99233cc7 100644 --- a/backend/tests/test_graph_clone.py +++ b/backend/tests/test_graph_clone.py @@ -1,7 +1,8 @@ # backend/tests/test_graph_clone.py +import asyncio import pytest from unittest.mock import AsyncMock, MagicMock, patch -import asyncio + def test_clone_graph_executes_two_queries(): """clone_graph should run exactly 2 Cypher queries: one for nodes, one for relationships.""" @@ -10,6 +11,7 @@ def test_clone_graph_executes_two_queries(): backend = GraphitiBackend.__new__(GraphitiBackend) executed_queries = [] + async def fake_execute_query(query, parameters=None, **kwargs): executed_queries.append(query) return [] @@ -21,18 +23,23 @@ def test_clone_graph_executes_two_queries(): combined = " ".join(executed_queries).lower() assert "group_id" in combined + def test_delete_graph_executes_detach_delete(): - """delete_graph should run a DETACH DELETE query.""" + """delete_graph should run a DETACH DELETE query against the correct group_id.""" from backend.app.graph.graphiti_backend import GraphitiBackend backend = GraphitiBackend.__new__(GraphitiBackend) executed_queries = [] + async def fake_execute_query(query, parameters=None, **kwargs): executed_queries.append(query) return [] backend._execute_neo4j_query = fake_execute_query - asyncio.run(backend.delete_graph_async("group_to_delete")) + + import backend.app.graph.graphiti_backend as gb_module + with patch.object(gb_module, '_run_async', side_effect=lambda coro: asyncio.run(coro)): + backend.delete_graph("group_to_delete") assert any("DETACH DELETE" in q for q in executed_queries)