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", "other_project"]) async def test_event_order_lock_precedes_business_writes_and_is_v2_only(repository, database): @asynccontextmanager async def transaction(): yield connection = SimpleNamespace( info=SimpleNamespace(dbname=database), execute=AsyncMock(), transaction=transaction, ) async with repository(connection, uuid4()).transaction(): if database == "tjwater_v2": connection.execute.assert_awaited_once_with( "SELECT pg_advisory_xact_lock(hashtextextended(%s,0))", (EVENT_ORDER_LOCK,), ) else: connection.execute.assert_not_awaited() def test_sync_producers_use_same_database_scoped_lock(): connection = SimpleNamespace(info=SimpleNamespace(dbname="tjwater_v2"), execute=Mock()) lock_event_transaction_sync(connection) connection.execute.assert_called_once_with( "SELECT pg_advisory_xact_lock(hashtextextended(%s,0))", (EVENT_ORDER_LOCK,), ) connection.info.dbname = "other_project" connection.execute.reset_mock() lock_event_transaction_sync(connection) connection.execute.assert_not_called()