from contextlib import asynccontextmanager from types import SimpleNamespace from unittest.mock import AsyncMock, Mock from uuid import uuid4 import pytest from app.infra.db.postgresql.operational_tasks import OperationalTaskRepository from app.infra.db.postgresql.task_alerts import TaskAlertRepository from app.infra.db.postgresql.workbench_events import ( EVENT_ORDER_LOCK, lock_event_transaction_sync, ) @pytest.fixture def anyio_backend(): return "asyncio" @pytest.mark.anyio @pytest.mark.parametrize("repository", [OperationalTaskRepository, TaskAlertRepository]) @pytest.mark.parametrize("database", ["tjwater_v2", "fengyang_v2", "other_project"]) async def test_event_order_lock_precedes_business_writes_in_each_project_database(repository, database): @asynccontextmanager async def transaction(): yield connection = SimpleNamespace( info=SimpleNamespace(dbname=database), execute=AsyncMock(), transaction=transaction, ) async with repository(connection, uuid4()).transaction(): connection.execute.assert_awaited_once_with( "SELECT pg_advisory_xact_lock(hashtextextended(%s,0))", (EVENT_ORDER_LOCK,), ) @pytest.mark.parametrize("database", ["tjwater_v2", "fengyang_v2", "other_project"]) def test_sync_producers_use_same_database_scoped_lock(database): connection = SimpleNamespace(info=SimpleNamespace(dbname=database), execute=Mock()) lock_event_transaction_sync(connection) connection.execute.assert_called_once_with( "SELECT pg_advisory_xact_lock(hashtextextended(%s,0))", (EVENT_ORDER_LOCK,), )