58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
|
|
import pytest
|
|
import respx
|
|
from httpx import Response
|
|
|
|
from app.clients.mci_server_client import MciServerClient
|
|
from app.models.event import EventStatus, EventType, OutboundEvent
|
|
from app.repositories.event_store import EventStore
|
|
from app.services.event_publisher import EventPublisher
|
|
|
|
|
|
@pytest.fixture
|
|
def publisher(tmp_path):
|
|
db_path = tmp_path / "events.db"
|
|
store = EventStore(str(db_path))
|
|
client = MciServerClient("http://mock-mci-server/msg-platform")
|
|
pub = EventPublisher(store, client, max_retry=2, base_delay_seconds=1, interval_seconds=0.1)
|
|
yield pub
|
|
|
|
|
|
@respx.mock
|
|
def test_publish_delivers_event(publisher):
|
|
route = respx.post("http://mock-mci-server/msg-platform/api/v1/channel-account/event").mock(
|
|
return_value=Response(200)
|
|
)
|
|
event = OutboundEvent(EventType.HEARTBEAT, "bot-001", "rescue", {"online_status": "online"})
|
|
publisher.store.save(event)
|
|
|
|
async def run():
|
|
await publisher._tick()
|
|
|
|
asyncio.run(run())
|
|
assert route.called
|
|
pending = publisher.store.fetch_pending(limit=10)
|
|
assert len(pending) == 0
|
|
|
|
|
|
@respx.mock
|
|
def test_publish_retries_then_dead_letter(publisher):
|
|
route = respx.post("http://mock-mci-server/msg-platform/api/v1/channel-account/event").mock(
|
|
return_value=Response(500)
|
|
)
|
|
event = OutboundEvent(EventType.HEARTBEAT, "bot-001", "rescue", {})
|
|
publisher.store.save(event)
|
|
|
|
async def run():
|
|
await publisher._tick()
|
|
|
|
asyncio.run(run())
|
|
assert route.call_count == 1
|
|
updated = publisher.store.get(event.event_id)
|
|
assert updated is not None
|
|
assert updated.status == EventStatus.RETRYING
|
|
assert updated.attempt_count == 1
|