Spaces:
Paused
Paused
File size: 2,760 Bytes
82eac1b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | """
Message Queue — Redis
─────────────────────
Push sentiment results → Dashboard (Lovable AI) รับแบบ real-time
ใช้ Redis List + Pub/Sub:
- LPUSH sentiment:results → queue สำหรับ polling
- PUBLISH sentiment:live → pub/sub สำหรับ WebSocket / SSE
"""
import json
import logging
import redis.asyncio as aioredis
from app.config import settings
logger = logging.getLogger(__name__)
QUEUE_KEY = "sentiment:results"
ALERT_KEY = "sentiment:alerts"
PUBSUB_CH = "sentiment:live"
ALERT_CH = "sentiment:alert_live"
class MessageQueue:
def __init__(self):
self._redis: aioredis.Redis | None = None
async def _get_redis(self) -> aioredis.Redis:
if self._redis is None:
self._redis = await aioredis.from_url(
settings.REDIS_URL,
encoding="utf-8",
decode_responses=True,
)
return self._redis
async def push(self, data: dict) -> None:
"""
Push sentiment result เข้า queue และ publish ให้ subscribers
"""
try:
r = await self._get_redis()
serialized = json.dumps(data, ensure_ascii=False)
# List (Lovable polling หรือ worker ดึงไปประมวลผลต่อ)
await r.lpush(QUEUE_KEY, serialized)
await r.ltrim(QUEUE_KEY, 0, 999) # เก็บแค่ 1,000 รายการล่าสุด
# Pub/Sub (real-time Dashboard WebSocket)
await r.publish(PUBSUB_CH, serialized)
logger.debug(f"✅ Queued: conv_id={data.get('conv_id')}")
except Exception as e:
logger.error(f"❌ Queue push failed: {e}")
async def push_alert(self, data: dict) -> None:
"""Push high-negative alert แยก channel"""
try:
r = await self._get_redis()
serialized = json.dumps(data, ensure_ascii=False)
await r.lpush(ALERT_KEY, serialized)
await r.publish(ALERT_CH, serialized)
logger.warning(f"🚨 Alert pushed: {data}")
except Exception as e:
logger.error(f"❌ Alert push failed: {e}")
async def get_recent(self, count: int = 50) -> list[dict]:
"""ดึง result ล่าสุดจาก queue สำหรับ initial load"""
try:
r = await self._get_redis()
items = await r.lrange(QUEUE_KEY, 0, count - 1)
return [json.loads(i) for i in items]
except Exception as e:
logger.error(f"❌ Queue read failed: {e}")
return []
# Singleton instance
message_queue = MessageQueue()
|