定时调度(beat)¶
beat 是独立进程里的调度器:到点就把任务投出去。多副本靠一个命名租约(__beat__)选主,
只有 leader 会触发,所以可以放心多起几个。
声明调度¶
from taskmq.schedule import cron, every
app.schedule(
cron("send_report", "0 9 * * *", tz="Asia/Shanghai"), # 每天 9:00(zoneinfo 本地时区,DST 正确)
every("cleanup", minutes=5, misfire="run_once"), # 每 5 分钟;错过就补一次
every("ping", seconds=30),
)
cron(name, expr, tz=):标准 5 段 cron(分 时 日 月 周),时区走zoneinfo;every(name, seconds= / minutes= / hours=, misfire=):固定间隔;misfire:"skip"(默认,错过就跳过)/"run_once"(错过补一次);- 首次部署只记基准不补跑,避免上线瞬间把所有历史窗口一次性打出去。
起 beat¶
taskmq --app myapp.tasks:app beat # 常驻
taskmq --app myapp.tasks:app beat --once # 只推进一轮(测试 / 外部 cron 驱动)
taskmq --app myapp.tasks:app dev # 本地开发:worker + beat 同进程
from taskmq import App, Config
from taskmq.worker.beat import Beat
beat = Beat(app, app.schedule_entries, state_path="taskmq.beat.json")
beat.run_forever(poll=1.0) # 或 beat.tick() 单步
状态与选主¶
- 调度状态(每个 entry 的
last_run/next_run)写在taskmq.beat.json(--state可改),只有 leader 写; - leader 通过 transport 的命名租约
__beat__选出,租约过期自动换主; - 所以 beat 需要 transport 支持
supports_leases(memory/sqlite/redis/postgres都支持;不支持的后端启动即报错)。
时区¶
Config(timezone="Asia/Shanghai") # App 默认时区
cron("send_report", "0 9 * * *") # 用 App 时区
cron("send_report", "0 9 * * *", tz="UTC") # 或者逐条覆盖