85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
import asyncio
|
|
import logging
|
|
import signal
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
from db.database import init_db, close_db_pool
|
|
from db.repository import Repository
|
|
from core.metrics import start_metrics_server
|
|
from core.llm import LLMClient
|
|
from core.queue import RedisQueue
|
|
from services.ai_processor import AIProcessor
|
|
from services.collector import CollectorService
|
|
from services.admin_bot import AdminBotService
|
|
from services.publisher import PublisherService
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
# Configure logging
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
|
)
|
|
logger = logging.getLogger("copykar.main")
|
|
|
|
async def main():
|
|
logger.info("Starting Copykar System with Immediate Admin Review & Paced Target Queues...")
|
|
|
|
# 1. Start Prometheus metrics server
|
|
metrics_port = int(os.getenv("METRICS_PORT", "8000"))
|
|
start_metrics_server(metrics_port)
|
|
|
|
# 2. Initialize Database schema & Redis Queue
|
|
await init_db()
|
|
logger.info("Database schema initialized.")
|
|
|
|
redis_queue = RedisQueue()
|
|
await redis_queue.connect()
|
|
|
|
repo = Repository()
|
|
llm = LLMClient()
|
|
|
|
# 3. Create Services
|
|
ai_processor = AIProcessor(repo=repo, llm=llm)
|
|
admin_bot = AdminBotService(repo=repo, ai_processor=ai_processor, queue=redis_queue)
|
|
collector = CollectorService(repo=repo, on_post_received=admin_bot.send_raw_review_post)
|
|
admin_bot.set_collector(collector)
|
|
|
|
# Publisher handles per-target delivery queues, intervals, and sleep windows
|
|
publisher = PublisherService(repo=repo, queue=redis_queue, client=collector.client)
|
|
|
|
# 4. Start all services
|
|
await admin_bot.start()
|
|
await collector.start(notify_fn=admin_bot.notify_admins)
|
|
await publisher.start()
|
|
|
|
logger.info("All Copykar services are active and running.")
|
|
|
|
# Graceful shutdown event
|
|
stop_event = asyncio.Event()
|
|
|
|
loop = asyncio.get_running_loop()
|
|
for sig in (signal.SIGINT, signal.SIGTERM):
|
|
try:
|
|
loop.add_signal_handler(sig, stop_event.set)
|
|
except NotImplementedError:
|
|
pass
|
|
|
|
try:
|
|
await stop_event.wait()
|
|
except (asyncio.CancelledError, KeyboardInterrupt):
|
|
pass
|
|
finally:
|
|
logger.info("Shutting down Copykar services...")
|
|
await collector.stop()
|
|
await publisher.stop()
|
|
await admin_bot.stop()
|
|
await redis_queue.close()
|
|
await close_db_pool()
|
|
logger.info("Copykar cleanly shut down.")
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|