app.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. """Quart + Hypercorn 应用工厂 —— 内建 DB + 日志服务 + XXL-JOB 生命周期"""
  2. import logging
  3. from quart import Quart
  4. from quart_cors import cors
  5. from supply.core.bootstrap import AppContext
  6. from supply.config import (
  7. AigcDatabaseConfig,
  8. LongArticlesDatabaseConfig,
  9. PiaoquanCrawlerDatabaseConfig,
  10. AliyunLogConfig,
  11. )
  12. from supply.infra.database.manager import DatabaseManager, create_backend
  13. from supply.infra.observability.logging import LogService
  14. import supply.jobs.test_handler # noqa: F401 — 触发 @xxl_job 装饰器注册
  15. from supply.jobs.xxl_config import XxlJobConfig
  16. from supply.jobs.xxl_executor import XxlJobExecutor
  17. from supply.server.xxl_endpoints import set_xxl_executor
  18. logger = logging.getLogger(__name__)
  19. _db_configs = {
  20. "aigc": AigcDatabaseConfig(),
  21. "long_articles": LongArticlesDatabaseConfig(),
  22. "piaoquan_crawler": PiaoquanCrawlerDatabaseConfig(),
  23. }
  24. def _build_backends() -> dict:
  25. """将配置字典转换为后端实例字典"""
  26. return {
  27. name: create_backend(name, config)
  28. for name, config in _db_configs.items()
  29. }
  30. def create_app() -> Quart:
  31. """创建 Quart 应用,内建 DB 连接池、日志服务和 XXL-JOB 执行器的生命周期管理"""
  32. logging.basicConfig(level=logging.INFO)
  33. log_service = LogService(AliyunLogConfig())
  34. db = DatabaseManager(_build_backends())
  35. xxl_config = XxlJobConfig()
  36. xxl_executor = XxlJobExecutor(xxl_config)
  37. set_xxl_executor(xxl_executor)
  38. app = Quart(__name__)
  39. app = cors(app, allow_origin="*")
  40. ctx = AppContext()
  41. ctx.on_startup(log_service.start)
  42. ctx.on_startup(db.init_pools)
  43. ctx.on_startup(xxl_executor.start)
  44. ctx.on_shutdown(xxl_executor.stop)
  45. ctx.on_shutdown(db.close_pools)
  46. ctx.on_shutdown(log_service.stop)
  47. @app.before_serving
  48. async def startup():
  49. logger.info("Starting application...")
  50. await ctx.start_up()
  51. logger.info("Application started successfully")
  52. @app.after_serving
  53. async def shutdown():
  54. logger.info("Shutting down application...")
  55. await ctx.shutdown()
  56. logger.info("Application shutdown successfully")
  57. return app