95 lines
2.7 KiB
Python
95 lines
2.7 KiB
Python
from contextlib import asynccontextmanager
|
|
from types import SimpleNamespace
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from app.api.v1.endpoints import workbench_events as endpoint
|
|
from app.auth.project_dependencies import ProjectContext
|
|
from app.infra.db.project_routing import ActiveProjectRouting
|
|
|
|
|
|
@pytest.fixture
|
|
def anyio_backend():
|
|
return "asyncio"
|
|
|
|
|
|
class FakeHub:
|
|
generation = 0
|
|
|
|
async def oldest_cursor(self):
|
|
return 5
|
|
|
|
async def current_cursor(self):
|
|
return 8
|
|
|
|
|
|
class FakeHubManager:
|
|
@asynccontextmanager
|
|
async def subscribe(self, _project_id, _dsn):
|
|
yield FakeHub()
|
|
|
|
|
|
class FakeMetadataRepository:
|
|
def __init__(self, routings):
|
|
self.routings = routings
|
|
self.session = SimpleNamespace(closed=False, close=self.close)
|
|
|
|
async def close(self):
|
|
self.session.closed = True
|
|
|
|
async def list_active_project_db_routings(self, _role):
|
|
return self.routings
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_expired_event_cursor_requires_snapshot_reset(monkeypatch):
|
|
project_id = uuid4()
|
|
dsn = "postgresql://test@db.example:5432/project_a"
|
|
routing = ActiveProjectRouting("project-a", dsn, project_id=project_id)
|
|
metadata = FakeMetadataRepository([
|
|
SimpleNamespace(project_id=project_id, dsn=dsn)
|
|
])
|
|
monkeypatch.setattr(endpoint, "workbench_event_hubs", FakeHubManager())
|
|
|
|
response = await endpoint.workbench_events(
|
|
after=1,
|
|
last_event_id=None,
|
|
ctx=ProjectContext(
|
|
project_id=project_id, project_code="project-a", user_id=uuid4(),
|
|
project_role="member",
|
|
),
|
|
routing=routing,
|
|
metadata_repo=metadata,
|
|
)
|
|
first = await anext(response.body_iterator)
|
|
|
|
assert metadata.session.closed is True
|
|
assert "event: reset_required" in first
|
|
assert '"cursor":1' in first
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_shared_business_database_disables_event_stream():
|
|
project_id = uuid4()
|
|
dsn = "postgresql://user:secret@db.example:5432/shared"
|
|
metadata = FakeMetadataRepository([
|
|
SimpleNamespace(project_id=project_id, dsn=dsn),
|
|
SimpleNamespace(project_id=uuid4(), dsn="postgresql://other:other@db.example/shared"),
|
|
])
|
|
|
|
with pytest.raises(HTTPException) as exc:
|
|
await endpoint.workbench_events(
|
|
after=0,
|
|
last_event_id=None,
|
|
ctx=ProjectContext(
|
|
project_id=project_id, project_code="project-a", user_id=uuid4(),
|
|
project_role="member",
|
|
),
|
|
routing=ActiveProjectRouting("project-a", dsn, project_id=project_id),
|
|
metadata_repo=metadata,
|
|
)
|
|
|
|
assert exc.value.status_code == 503
|