APScheduler是否存在run_pending()方法?如何补跑错过的定时任务?
APScheduler 错过执行任务的补跑实现方案
场景说明
- 业务需求为每日00:00自动执行指定校验逻辑
- 当前基于
BackgroundScheduler实现定时调度,遇到的问题为:程序重启、进程休眠导致任务到点未触发时,没有明确的机制补跑错过的任务 - 此前使用其他调度器时可通过
run_pending()拉取待执行队列完成任务运行,对APScheduler的同类处理逻辑不熟悉
核心机制说明
APScheduler 内置了针对错过触发时间的任务处理能力,不需要单独实现类似run_pending()的方法,核心通过misfire_grace_time参数控制补跑范围:
- 参数定义:当任务到点未触发时,只要错过的时间在设置的阈值范围内,调度器就会在任务重新可执行时自动补跑该任务,阈值单位为秒
- 参数可配置在两个层级:
- 全局层级:实例化调度器时设置,对所有任务生效
- 任务层级:调用
add_job添加单个任务时设置,优先级高于全局配置,可针对单个任务调整补跑宽容度
- 注意:APScheduler 默认的全局
misfire_grace_time为1秒,意味着只要任务错过触发时间超过1秒就会直接判定为过期,不会触发补跑
现有代码的问题与修改示例
现存问题
- 实例化调度器时未设置
misfire_grace_time,沿用默认1秒的阈值,完全无法满足跨时段补跑需求 - 调度器使用默认的内存任务存储,进程重启后所有任务的触发状态会被清空,即使配置了补跑阈值,也无法实现跨进程重启的补跑逻辑
- 代码中存在类型不匹配问题:将配置值转为int后,与字符串类型的"1"、"0"做相等判断,运行时会触发逻辑异常
- 遗漏了
datetime模块的导入,实际运行会触发导入报错
修改后的可运行代码
# 补充datetime导入 import datetime from apscheduler.schedulers.background import BackgroundScheduler import PREFS beginDate = datetime.date.today().strftime("%Y/%m/%d") prefs = {"kanjiNum": 0, "studyToday": 0, "beginDate": beginDate, "lostKanji": 0} MainPrefs = PREFS.PREFS(prefs=prefs, filename="DailyDoseOfKanjis_Prefs") # 实例化调度器时设置全局24小时的补跑宽容度,同时指定时区避免触发时间偏移 scheduler = BackgroundScheduler(timezone="Asia/Shanghai", misfire_grace_time=86400) scheduler.start() def DailyCheck(): study_status = int(MainPrefs.ReadPrefs()["studyToday"]) if study_status == 1: print("You did study") MainPrefs.WritePrefs("studyToday", 0) elif study_status == 0: print("You didn't study") lost_num = int(MainPrefs.ReadPrefs()["lostKanji"]) MainPrefs.WritePrefs("lostKanji", lost_num + 1) MainPrefs.WritePrefs("kanjiNum", BeginKanji()) # 添加每日00:00执行的任务,单独配置12小时的补跑窗口 scheduler.add_job( DailyCheck, 'cron', second=0, minute=0, hour=0, id='check', misfire_grace_time=43200 ) # 添加每日8:51执行的打印任务,单独配置1小时的补跑窗口 scheduler.add_job( lambda: print("yea"), 'cron', second=0, minute=51, hour=8, id='yea', misfire_grace_time=3600 )
注意事项
- 如果需要跨进程重启实现补跑,必须给APScheduler配置持久化任务存储(如基于SQLAlchemy的文件/数据库存储),默认的内存存储无法保留进程退出前的任务触发记录
- 不要将
misfire_grace_time设置得过大,否则可能在任务触发时间过期很久后才被补跑,引发不符合预期的业务逻辑 - 部署时需要统一指定调度器时区,避免因系统时区偏移导致任务触发时间和预期不符
内容的提问来源于stack exchange,提问作者Patitotective
相关产品推荐
相关产品推荐

