在处理任务调度时,一个常见的问题是在任务队列繁忙时如何正确处理任务的重新调度。具体到某个调度系统,当任务调度函数 run() 在尝试创建任务时返回 Busy 状态,系统会将任务的 next_run_at 时间设置为当前时间加上一个重试间隔 BUSY_RETRY_MS。这种做法虽然可以使得任务在稍后再次尝试执行,但存在一个问题:它会覆盖原始的 due 时间,导致任务在重新执行时,其网格计算起点被改变,从而影响任务的正常调度。
为了重现这个问题,我们可以设定一个任务,其首次执行时间为 10:00,执行间隔为 60 分钟。如果在 10:00 时任务队列已经满载,那么任务将无法立即执行,系统会在 10:01 尝试再次执行,随后在 11:01 和 12:01 继续尝试。每次任务因为队列繁忙而无法执行时,next_run_at 都会被累加重试间隔,这会导致 request_key 发生变化,从而使得任务不再是同一槽位的重试。
针对这个问题,我们可以考虑两种修复方向:
- 不覆盖
next_run_at,而是另存一个retry_at字段来记录下一次重试的时间; - 在任务重试成功后,仍然使用原始的
due时间来计算下一个执行槽位。
目前来看,测试代码 schedules_tests.rs 中缺少了处理任务繁忙场景的用例,这可能导致在实际环境中难以发现和调试此类问题。因此,增加相应的测试用例是必要的,以确保系统能够正确处理任务队列繁忙的情况。
评论已关闭