Files
next-tjwater-server/tests/unit/test_workbench_event_hub.py
T

92 lines
2.8 KiB
Python

import asyncio
from types import SimpleNamespace
from unittest.mock import AsyncMock
from uuid import uuid4
import pytest
from app.infra.db.postgresql.workbench_event_hub import WorkbenchEventHub, WorkbenchEventHubManager
from app.infra.db.postgresql import workbench_event_hub as hub_module
@pytest.fixture
def anyio_backend():
return "asyncio"
@pytest.mark.anyio
async def test_project_subscribers_share_one_hub_and_idle_close(monkeypatch):
start = AsyncMock()
close = AsyncMock()
monkeypatch.setattr(WorkbenchEventHub, "start", start)
monkeypatch.setattr(WorkbenchEventHub, "close", close)
manager = WorkbenchEventHubManager(idle_seconds=0.01)
project_id = uuid4()
async with manager.subscribe(project_id, "postgresql://test/db") as first:
async with manager.subscribe(project_id, "postgresql://test/db") as second:
assert first is second
assert first.subscribers == 2
assert first.subscribers == 1
await asyncio.sleep(0.03)
assert len(manager._hubs) == 0
close.assert_awaited_once()
@pytest.mark.anyio
async def test_idle_subscribers_share_cursor_reads_and_notification_invalidates_the_cache(monkeypatch):
reads = 0
class Repository:
def __init__(self, *_args):
pass
async def read_after(self, _after):
nonlocal reads
reads += 1
return []
monkeypatch.setattr(hub_module, "WorkbenchEventRepository", Repository)
hub = WorkbenchEventHub(uuid4(), "postgresql://test/db")
hub._connection = SimpleNamespace(closed=False)
monkeypatch.setattr(hub, "start", AsyncMock())
await asyncio.gather(*(hub.read_after(0) for _ in range(20)))
assert reads == 1
await hub._wake()
await asyncio.gather(*(hub.read_after(0) for _ in range(20)))
assert reads == 2
@pytest.mark.anyio
async def test_notification_during_read_does_not_cache_stale_results(monkeypatch):
entered, release = asyncio.Event(), asyncio.Event()
reads = 0
class Repository:
def __init__(self, *_args):
pass
async def read_after(self, _after):
nonlocal reads
reads += 1
if reads == 1:
entered.set()
await release.wait()
return []
monkeypatch.setattr(hub_module, "WorkbenchEventRepository", Repository)
hub = WorkbenchEventHub(uuid4(), "postgresql://test/db")
hub._connection = SimpleNamespace(closed=False)
monkeypatch.setattr(hub, "start", AsyncMock())
first = asyncio.create_task(hub.read_after(0))
await entered.wait()
await hub._wake()
release.set()
await first
await hub.read_after(0)
assert reads == 2
for cursor in range(100):
await hub.read_after(cursor)
assert len(hub._reads) == 32