feat(pubsub): get_event_bus() late-import accessor
This commit is contained in:
@@ -56,3 +56,15 @@ class EventBus:
|
|||||||
while True:
|
while True:
|
||||||
yield await queue.get()
|
yield await queue.get()
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
|
|
||||||
|
|
||||||
|
def get_event_bus() -> EventBus:
|
||||||
|
"""Return the process-wide EventBus attached to the FastAPI app state.
|
||||||
|
|
||||||
|
Late-imports ``cyclone.api`` to avoid a circular import at module
|
||||||
|
load time (the API module imports pubsub indirectly via lifespan).
|
||||||
|
Tests stub this via monkeypatch.
|
||||||
|
"""
|
||||||
|
from cyclone.api import app # late import to avoid circular
|
||||||
|
|
||||||
|
return app.state.event_bus
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import time
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from cyclone.pubsub import EventBus
|
from cyclone.pubsub import EventBus, get_event_bus
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@@ -97,3 +97,13 @@ async def test_multiple_concurrent_subscribers_each_get_all_events():
|
|||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
seen.append(await asyncio.wait_for(q.__anext__(), timeout=0.5))
|
seen.append(await asyncio.wait_for(q.__anext__(), timeout=0.5))
|
||||||
assert [e["i"] for e in seen] == [0, 1, 2, 3, 4]
|
assert [e["i"] for e in seen] == [0, 1, 2, 3, 4]
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_event_bus_raises_when_app_state_uninitialized():
|
||||||
|
"""get_event_bus() late-imports cyclone.api; without a running app,
|
||||||
|
accessing app.state.event_bus raises AttributeError."""
|
||||||
|
# Don't import cyclone.api at module level — that would force a load
|
||||||
|
# and could mask the real failure. Just call the helper and expect
|
||||||
|
# the AttributeError to surface from app.state.
|
||||||
|
with pytest.raises((AttributeError, RuntimeError)):
|
||||||
|
get_event_bus()
|
||||||
|
|||||||
Reference in New Issue
Block a user