deer-flow/backend/tests/blocking_io/test_project_memory_routes.py
Wenchao An 9699f04cdc
feat(projects): add visible project memory with extraction controls (#8117)
* feat(projects): add visible project memory with extraction controls

* fix(projects): avoid replaying committed memory extractions

* chore(ci): retrigger project memory checks

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-11-12 09:09:44 +08:00

59 lines
2.5 KiB
Python

"""Every project-memory route offloads its synchronous repository work."""
import asyncio
import threading
from types import SimpleNamespace
import pytest
import test_project_memory as memory_tests
from _router_auth_helpers import call_unwrapped
from app.gateway.routers import projects
from deerflow.config.projects_config import ProjectsConfig
@pytest.fixture
def repo(tmp_path):
yield from memory_tests.repo.__wrapped__(tmp_path)
@pytest.mark.asyncio
@pytest.mark.parametrize("operation", ["get", "set_enabled", "delete", "promote"])
async def test_memory_routes_keep_repository_io_off_the_loop(repo, tmp_path, monkeypatch, operation):
await asyncio.to_thread(repo.apply, "p1", "u1", "t1", 0, {"newFacts": [memory_tests.fact()]})
state = await asyncio.to_thread(repo.get, "p1", "u1")
fact_id = state["facts"][0]["id"]
marker = tmp_path / "repository-io.txt"
await asyncio.to_thread(marker.write_text, "worker read", encoding="utf-8")
loop_thread = threading.get_ident()
original = getattr(repo, operation)
calls = []
def observed(*args, **kwargs):
# The strict detector catches this real read if either offload is removed.
assert marker.read_text(encoding="utf-8") == "worker read"
assert threading.get_ident() != loop_thread
calls.append(args)
return original(*args, **kwargs)
monkeypatch.setattr(repo, operation, observed)
monkeypatch.setattr(projects, "get_project_memory_repository", lambda: repo)
monkeypatch.setattr(projects, "get_effective_user_id", lambda: "u1")
monkeypatch.setattr(projects, "_projects_config", ProjectsConfig)
request = SimpleNamespace()
if operation == "get":
result = await call_unwrapped(projects.get_project_memory, "p1", request)
assert result.facts[0].id == fact_id
elif operation == "set_enabled":
result = await call_unwrapped(projects.patch_project_memory, "p1", projects.ProjectMemoryPatch(enabled=False), request)
assert result.enabled is False
elif operation == "delete":
result = await call_unwrapped(projects.delete_project_memory, "p1", fact_id, request)
assert result.facts == []
else:
result = await call_unwrapped(projects.promote_project_memory, "p1", fact_id, projects.ProjectMemoryPromotion(expected_instructions=""), request)
assert result.instructions == "- Reports exclude tax"
assert result.memory.facts == []
assert len(calls) == 1
assert calls[0][:2] == ("p1", "u1")