feat(workbench): persist operational workflows and events
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
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
|
||||
Reference in New Issue
Block a user