64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
import os
|
|
import json
|
|
import logging
|
|
from typing import Optional, Dict, Any
|
|
import redis.asyncio as redis
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
REDIS_URL = os.getenv("REDIS_URL", "redis://copykar_redis:6379/0" if os.path.exists("/app") else "redis://localhost:6379/0")
|
|
|
|
class RedisQueue:
|
|
def __init__(self, redis_url: Optional[str] = None):
|
|
self.redis_url = redis_url or REDIS_URL
|
|
self.client: Optional[redis.Redis] = None
|
|
|
|
async def connect(self):
|
|
if not self.client:
|
|
self.client = redis.from_url(self.redis_url, decode_responses=True)
|
|
await self.client.ping()
|
|
logger.info(f"Connected to Redis at {self.redis_url}")
|
|
|
|
def _get_target_key(self, target_id: int) -> str:
|
|
return f"copykar:queue:target:{target_id}"
|
|
|
|
async def push_target_post(self, target_id: int, payload: Dict[str, Any]):
|
|
if not self.client:
|
|
await self.connect()
|
|
key = self._get_target_key(target_id)
|
|
raw_json = json.dumps(payload)
|
|
await self.client.rpush(key, raw_json)
|
|
logger.info(f"Enqueued post {payload.get('post_id')} to Target #{target_id} queue [{key}]")
|
|
|
|
async def pop_target_post(self, target_id: int) -> Optional[Dict[str, Any]]:
|
|
if not self.client:
|
|
await self.connect()
|
|
key = self._get_target_key(target_id)
|
|
raw = await self.client.lpop(key)
|
|
if raw:
|
|
try:
|
|
return json.loads(raw)
|
|
except Exception as e:
|
|
logger.error(f"Error parsing queue JSON from {key}: {e}")
|
|
return None
|
|
|
|
async def get_target_queue_size(self, target_id: int) -> int:
|
|
if not self.client:
|
|
await self.connect()
|
|
key = self._get_target_key(target_id)
|
|
return await self.client.llen(key)
|
|
|
|
async def get_total_queued_posts(self) -> int:
|
|
if not self.client:
|
|
await self.connect()
|
|
keys = await self.client.keys("copykar:queue:target:*")
|
|
total = 0
|
|
for k in keys:
|
|
total += await self.client.llen(k)
|
|
return total
|
|
|
|
async def close(self):
|
|
if self.client:
|
|
await self.client.aclose()
|
|
logger.info("Redis connection closed.")
|