add 添加基于crontab表达式完成的调度任务组件

This commit is contained in:
2026-02-02 00:02:36 +08:00
parent ae9f7a681f
commit f16ca4fbdc
4 changed files with 335 additions and 398 deletions

View File

@@ -64,6 +64,12 @@ from app.services.pdf_converter import (
markdown_file_to_pdf_bytes,
read_file_content,
)
from app.core.ScheduledTaskManager import ScheduledTaskManager
from app.core.ScheduledTask import ScheduledTask
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
"""
@api Server Application
@@ -78,6 +84,122 @@ app.add_middleware(
allow_headers=["*"],
)
# ==================== 调度任务管理器 ====================
# 全局调度任务管理器实例,用于管理所有定时任务
# 使用 Optional 类型注解,表示可能为 None服务启动前/关闭后)
_task_manager: Optional[ScheduledTaskManager] = None
def get_task_manager() -> Optional[ScheduledTaskManager]:
"""
获取全局调度任务管理器实例
Returns:
Optional[ScheduledTaskManager]: 调度器实例,如果未初始化则返回 None
使用示例:
task_manager = get_task_manager()
if task_manager:
task_manager.add_daily_task("task_id", 10, 30, some_function)
"""
global _task_manager
return _task_manager
# 定义定时任务函数
def scheduled_method():
"""定时任务执行的函数"""
logger.info("执行定时任务...")
@app.on_event("startup")
async def startup_event():
"""
FastAPI 服务启动事件处理函数
在服务启动时自动执行,完成以下初始化工作:
1. 创建 ScheduledTaskManager 实例
2. 启动后台调度器(基于 APScheduler BackgroundScheduler
3. 添加定时任务
4. 记录初始化日志
注意:此函数在 FastAPI 接收任何请求之前执行
"""
global _task_manager
logger.info("=" * 60)
logger.info("服务启动初始化...")
logger.info("=" * 60)
try:
# 步骤1: 创建调度任务管理器实例
_task_manager = ScheduledTaskManager()
logger.info("调度任务管理器已初始化")
# 步骤2: 启动调度器
_task_manager.start()
logger.info("任务调度器已启动")
# 步骤3: 创建 ScheduledTask 实例并添加定时任务
scheduled_task = ScheduledTask(task_manager=_task_manager)
scheduled_task.add_cron_task(
task_id="main-task",
task_name="调度任务执行启动",
crontab="*/1 * * * *", # 每分钟执行一次
task_func=scheduled_method, # 注意:不要加括号
args=(), # 位置参数(元组)
kwargs={} # 关键字参数(字典)
)
logger.info("已添加定时任务: main-task (每分钟执行一次)")
logger.info("=" * 60)
logger.info("服务启动初始化完成")
logger.info("=" * 60)
except Exception as e:
logger.error(f"服务启动初始化失败: {e}")
# 重新抛出异常,让 FastAPI 知道启动失败
raise
@app.on_event("shutdown")
async def shutdown_event():
"""
FastAPI 服务关闭事件处理函数
在服务关闭时自动执行,完成以下清理工作:
1. 优雅关闭调度器(等待正在执行的任务完成)
2. 清理全局变量引用
注意:此函数在 FastAPI 停止接收新请求后执行
"""
global _task_manager
logger.info("=" * 60)
logger.info("服务关闭中...")
logger.info("=" * 60)
try:
# 检查调度器是否已初始化
if _task_manager is not None:
# 关闭调度器
# shutdown() 会等待正在执行的任务完成,然后终止后台线程
_task_manager.shutdown()
logger.info("任务调度器已关闭")
# 清理全局变量引用,释放内存
_task_manager = None
logger.info("=" * 60)
logger.info("服务已关闭")
logger.info("=" * 60)
except Exception as e:
# 记录错误但不重新抛出,确保服务能正常关闭
logger.error(f"服务关闭时发生错误: {e}")
# ==================== 静态文件挂载 ====================
try:
_ui_dir = Path(__file__).resolve().parents[2] / "frontend" / "dist"
if _ui_dir.exists():