"""Точка входа: `pipu-rec serve` (онлайн-API) или `pipu-rec analyze` (воркер аудиоанализа).""" import argparse import logging import psycopg import redis.asyncio as aioredis import uvicorn from pipu_rec.analysis.worker import Worker from pipu_rec.api.app import create_app from pipu_rec.settings import Settings from pipu_rec.wave.contexts import load_contexts from pipu_rec.wave.service import WaveService log = logging.getLogger("pipu_rec") def _serve(settings: Settings) -> None: rdb = aioredis.Redis.from_url(settings.redis_url, socket_connect_timeout=2, socket_timeout=2) 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() wave = WaveService(settings.database_url, settings.redis_url, load_contexts(settings.contexts_path)) app = create_app(settings, {"postgres": check_postgres, "redis": check_redis}, wave) uvicorn.run(app, host=settings.http_host, port=settings.http_port, log_level=settings.log_level) def _analyze(settings: Settings, workers: int) -> None: Worker( settings.database_url, settings.library_root, settings.library_host_root, workers, settings.ffmpeg_path, ).run_forever() 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()