app.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """Quart + Hypercorn 应用工厂 —— 全局配置驱动,DB + 日志 + XXL-JOB 生命周期内建"""
  2. import logging
  3. from quart import Quart
  4. from quart_cors import cors
  5. from src.core.bootstrap import AppContext
  6. from src.config import GlobalConfig
  7. from src.infra.database import DatabaseManager, create_backend
  8. from src.infra.observability import LogService
  9. from src.infra.xxl_jobs import XxlJobExecutor
  10. from src.config.logging_config import setup_logging
  11. from src.handlers import discover_and_register
  12. from src.handlers._utils import set_db
  13. from src.server.xxl_endpoints import set_xxl_executor
  14. logger = logging.getLogger(__name__)
  15. def create_app(global_config: GlobalConfig = None) -> Quart:
  16. """创建 Quart 应用
  17. 统一从 GlobalConfig 获取所有配置,消除散落的 Config() 调用。
  18. 可选传入 custom_config 用于测试覆盖。
  19. Args:
  20. global_config: 可选的自定义配置,默认从环境变量加载
  21. """
  22. if global_config is None:
  23. global_config = GlobalConfig()
  24. logging.basicConfig(level=logging.INFO)
  25. setup_logging()
  26. # 初始化各层依赖 —— 全部从 global_config 取值
  27. log_service = LogService(global_config.aliyun_log)
  28. db = DatabaseManager(
  29. {
  30. name: create_backend(name, config)
  31. for name, config in global_config.active_db_configs().items()
  32. }
  33. )
  34. discover_and_register()
  35. xxl_executor = XxlJobExecutor(global_config.xxl_job)
  36. set_xxl_executor(xxl_executor)
  37. set_db(db)
  38. app = Quart(__name__)
  39. app = cors(app, allow_origin="*")
  40. # 生命周期
  41. ctx = AppContext()
  42. ctx.on_startup(log_service.start)
  43. ctx.on_startup(db.init_pools)
  44. ctx.on_startup(xxl_executor.start)
  45. ctx.on_shutdown(xxl_executor.stop)
  46. ctx.on_shutdown(db.close_pools)
  47. ctx.on_shutdown(log_service.stop)
  48. @app.before_serving
  49. async def startup():
  50. logger.info("Starting application...")
  51. await ctx.start_up()
  52. logger.info("Application started successfully")
  53. @app.after_serving
  54. async def shutdown():
  55. logger.info("Shutting down application...")
  56. await ctx.shutdown()
  57. logger.info("Application shutdown successfully")
  58. return app