82 lines
2.3 KiB
Python
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
|