"""Точка входа: `pipu-rec serve` (онлайн-API) или `pipu-rec analyze` (воркер аудиоанализа).""" import argparse import asyncio import logging import psycopg import redis.asyncio as aioredis import uvicorn from pipu_rec.api.app import create_app from pipu_rec.settings import Settings log = logging.getLogger("pipu_rec") def _serve(settings: Settings) -> None: rdb = aioredis.Redis.from_url(settings.redis_url) async def check_postgres() -> None: async with await psycopg.AsyncConnection.connect(settings.database_url, connect_timeout=2) as conn: await conn.execute("SELECT 1") async def check_redis() -> None: await rdb.ping() app = create_app(settings, {"postgres": check_postgres, "redis": check_redis}) uvicorn.run(app, host=settings.http_host, port=settings.http_port, log_level=settings.log_level) def _analyze(settings: Settings, workers: int) -> None: # Аудиоанализ (Essentia) появится в M4; сейчас воркер только держит процесс живым. log.info("analyzer started: workers=%d version=%s (no-op until M4)", workers, settings.version) async def idle() -> None: while True: await asyncio.sleep(3600) asyncio.run(idle()) def main() -> None: parser = argparse.ArgumentParser(prog="pipu-rec") sub = parser.add_subparsers(dest="cmd", required=True) sub.add_parser("serve", help="внутренний API рекомендаций") analyze = sub.add_parser("analyze", help="воркер аудиоанализа") analyze.add_argument("--workers", type=int, default=4) args = parser.parse_args() settings = Settings() logging.basicConfig(level=settings.log_level.upper()) if args.cmd == "serve": _serve(settings) else: _analyze(settings, args.workers) if __name__ == "__main__": main()