"""Quart + Hypercorn 应用工厂 —— 内建 DB + 日志服务 + XXL-JOB 生命周期""" import logging from quart import Quart from quart_cors import cors from supply.core.bootstrap import AppContext from supply.config import ( AigcDatabaseConfig, LongArticlesDatabaseConfig, PiaoquanCrawlerDatabaseConfig, AliyunLogConfig, ) from supply.infra.database.manager import DatabaseManager, create_backend from supply.infra.observability.logging import LogService import supply.jobs.test_handler # noqa: F401 — 触发 @xxl_job 装饰器注册 from supply.jobs.xxl_config import XxlJobConfig from supply.jobs.xxl_executor import XxlJobExecutor from supply.server.xxl_endpoints import set_xxl_executor logger = logging.getLogger(__name__) _db_configs = { "aigc": AigcDatabaseConfig(), "long_articles": LongArticlesDatabaseConfig(), "piaoquan_crawler": PiaoquanCrawlerDatabaseConfig(), } def _build_backends() -> dict: """将配置字典转换为后端实例字典""" return { name: create_backend(name, config) for name, config in _db_configs.items() } def create_app() -> Quart: """创建 Quart 应用,内建 DB 连接池、日志服务和 XXL-JOB 执行器的生命周期管理""" logging.basicConfig(level=logging.INFO) log_service = LogService(AliyunLogConfig()) db = DatabaseManager(_build_backends()) xxl_config = XxlJobConfig() xxl_executor = XxlJobExecutor(xxl_config) set_xxl_executor(xxl_executor) app = Quart(__name__) app = cors(app, allow_origin="*") ctx = AppContext() ctx.on_startup(log_service.start) ctx.on_startup(db.init_pools) ctx.on_startup(xxl_executor.start) ctx.on_shutdown(xxl_executor.stop) ctx.on_shutdown(db.close_pools) ctx.on_shutdown(log_service.stop) @app.before_serving async def startup(): logger.info("Starting application...") await ctx.start_up() logger.info("Application started successfully") @app.after_serving async def shutdown(): logger.info("Shutting down application...") await ctx.shutdown() logger.info("Application shutdown successfully") return app