fix(workbench): configure psycopg snapshot transaction
Open the psycopg transaction without unsupported SQLAlchemy-style options, then set the PostgreSQL isolation and read-only characteristics before the first query. Cover the exact snapshot endpoint path with a regression test.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from datetime import datetime, timezone
|
||||
from types import SimpleNamespace
|
||||
from uuid import uuid4
|
||||
|
||||
@@ -43,6 +44,77 @@ class FakeMetadataRepository:
|
||||
return self.routings
|
||||
|
||||
|
||||
class FakeSnapshotConnection:
|
||||
def __init__(self):
|
||||
self.statements = []
|
||||
|
||||
@asynccontextmanager
|
||||
async def transaction(self):
|
||||
yield
|
||||
|
||||
async def execute(self, statement):
|
||||
self.statements.append(statement)
|
||||
|
||||
|
||||
class FakeEventRepository:
|
||||
def __init__(self, _conn, _project_id):
|
||||
pass
|
||||
|
||||
async def current_cursor(self):
|
||||
return 12
|
||||
|
||||
|
||||
class FakeOperationalTaskService:
|
||||
async def list(self, **_kwargs):
|
||||
return [], None
|
||||
|
||||
async def list_notifications(self, **_kwargs):
|
||||
return [], None
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_sync_snapshot_starts_psycopg_read_only_repeatable_read_transaction(monkeypatch):
|
||||
project_id = uuid4()
|
||||
conn = FakeSnapshotConnection()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
async def fake_runtime(**_kwargs):
|
||||
return {
|
||||
"availability": "not_configured",
|
||||
"source": "none",
|
||||
"scenario_availability": "not_configured",
|
||||
"artifact_availability": "not_configured",
|
||||
"schedule_availability": "not_configured",
|
||||
"work_order_availability": "not_configured",
|
||||
"alert_availability": "not_configured",
|
||||
"generated_at": now,
|
||||
"conditions": [],
|
||||
"alerts": [],
|
||||
"scenarios": [],
|
||||
"latest_analysis": None,
|
||||
"work_orders": [],
|
||||
}
|
||||
|
||||
monkeypatch.setattr(endpoint, "WorkbenchEventRepository", FakeEventRepository)
|
||||
monkeypatch.setattr(endpoint, "workbench_runtime", fake_runtime)
|
||||
monkeypatch.setattr(endpoint, "_service", lambda _ctx, _conn: FakeOperationalTaskService())
|
||||
|
||||
snapshot = await endpoint.workbench_sync_snapshot(
|
||||
ctx=ProjectContext(
|
||||
project_id=project_id,
|
||||
project_code="project-a",
|
||||
user_id=uuid4(),
|
||||
project_role="member",
|
||||
),
|
||||
conn=conn,
|
||||
)
|
||||
|
||||
assert snapshot.event_cursor == 12
|
||||
assert conn.statements == [
|
||||
"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY"
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_expired_event_cursor_requires_snapshot_reset(monkeypatch):
|
||||
project_id = uuid4()
|
||||
|
||||
Reference in New Issue
Block a user