xianyufaka/order_event_hub.py
2026-04-15 22:56:44 +08:00

82 lines
2.3 KiB
Python

import queue
import threading
import time
from collections import defaultdict
from typing import Any, Dict, Optional
from loguru import logger
class OrderEventHub:
"""进程内订单事件中心,按 user_id 广播订单更新。"""
def __init__(self):
self._lock = threading.RLock()
self._subscribers = defaultdict(set)
def subscribe(self, user_id: int, maxsize: int = 100):
subscriber = queue.Queue(maxsize=maxsize)
with self._lock:
self._subscribers[user_id].add(subscriber)
return subscriber
def unsubscribe(self, user_id: int, subscriber):
with self._lock:
subscribers = self._subscribers.get(user_id)
if not subscribers:
return
subscribers.discard(subscriber)
if not subscribers:
self._subscribers.pop(user_id, None)
def publish(self, user_id: int, event: Dict[str, Any]):
with self._lock:
subscribers = list(self._subscribers.get(user_id, set()))
for subscriber in subscribers:
try:
subscriber.put_nowait(event)
except queue.Full:
try:
subscriber.get_nowait()
except queue.Empty:
pass
try:
subscriber.put_nowait(event)
except queue.Full:
logger.warning(f"订单事件队列仍然已满,丢弃事件: user_id={user_id}")
order_event_hub = OrderEventHub()
def build_order_update_event(order: Dict[str, Any], source: str = "unknown") -> Dict[str, Any]:
return {
"type": "order.updated",
"source": source,
"timestamp": int(time.time() * 1000),
"order": order,
}
def publish_order_update_event(order_id: str, source: str = "unknown") -> Optional[Dict[str, Any]]:
from db_manager import db_manager
order = db_manager.get_order_by_id(order_id)
if not order:
return None
cookie_id = order.get('cookie_id')
if not cookie_id:
return None
cookie_info = db_manager.get_cookie_details(cookie_id)
user_id = cookie_info.get('user_id') if cookie_info else None
if user_id is None:
return None
event = build_order_update_event(order, source=source)
order_event_hub.publish(user_id, event)
return event