- 后端新增进程内事件总线与 /api/huya/external-orders/ws\n- 所有写接口成功后发布轻量失效事件\n- 前端自动重连、静默刷新、断线兜底轮询
62 lines
1.9 KiB
Python
62 lines
1.9 KiB
Python
"""协作台账实时事件总线:revision、跨线程投递、队列满时保留最新事件。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import threading
|
|
|
|
from web.backend.services.huya_collab_events import CollabEventHub
|
|
|
|
|
|
def test_publish_increments_revision_without_subscribers():
|
|
hub = CollabEventHub()
|
|
|
|
first = hub.publish(scope="orders", action="order.create", actor_id=7)
|
|
second = hub.publish(scope="shops", action="shop.create", actor_id=8)
|
|
|
|
assert first["revision"] == 1
|
|
assert second["revision"] == 2
|
|
assert hub.ready_event() == {"type": "collab.ready", "revision": 2}
|
|
assert hub.ping_event() == {"type": "collab.ping", "revision": 2}
|
|
|
|
|
|
def test_publish_delivers_from_worker_thread():
|
|
async def scenario():
|
|
hub = CollabEventHub()
|
|
queue = hub.subscribe()
|
|
|
|
worker = threading.Thread(
|
|
target=lambda: hub.publish(
|
|
scope="orders", action="order.update", actor_id=9
|
|
)
|
|
)
|
|
worker.start()
|
|
worker.join(timeout=2)
|
|
|
|
event = await asyncio.wait_for(queue.get(), timeout=2)
|
|
assert event["type"] == "collab.invalidate"
|
|
assert event["scope"] == "orders"
|
|
assert event["action"] == "order.update"
|
|
assert event["actor_id"] == 9
|
|
assert event["revision"] == 1
|
|
|
|
asyncio.run(scenario())
|
|
|
|
|
|
def test_queue_overflow_keeps_latest_event():
|
|
async def scenario():
|
|
hub = CollabEventHub()
|
|
queue = hub.subscribe()
|
|
for _ in range(101):
|
|
hub.publish(scope="orders", action="order.update", actor_id=1)
|
|
|
|
await asyncio.sleep(0.05)
|
|
assert queue.qsize() <= queue.maxsize
|
|
latest = await asyncio.wait_for(queue.get(), timeout=2)
|
|
# 队列满时丢掉旧事件,但最后一条一定是 revision 最大的
|
|
while not queue.empty():
|
|
latest = queue.get_nowait()
|
|
assert latest["revision"] == 101
|
|
|
|
asyncio.run(scenario())
|