分析与解决方案:KernelSU 解决方案中的调度问题修复

问题所在

在 KernelSU 解决方案的后端调度模块中,位于文件 backend/src/schedules.rs 的 run 函数中,存在一个处理 Err(AppError::Busy) 错误分支的逻辑问题。具体来说,当调度任务因为队列繁忙而失败时,代码将 next_run_at 设置为 now + BUSY_RETRY_MS,而不是保留原始的 due 时间。这种做法导致后续的调度执行时间产生偏差,每次执行都基于这个被修改过的时间点,而不是原始计划时间。

行为描述

当任务遇到 Err(AppError::Busy) 错误时,调度系统会将下一次执行时间设置为当前时间加上 BUSY_RETRY_MS 毫秒,而不是等待到原始的 due 时间。这意味着,如果任务因为队列繁忙而未能执行,它将不会按照原计划的时间执行,而是会延迟固定的 BUSY_RETRY_MS 时间后再次尝试。这种策略会导致任务执行时间逐渐偏离预期的执行时间点,造成时间上的偏差累积。

问题复现步骤

  1. 新建一个计划任务,设置首次执行时间为 10:00,并设置间隔为 60 分钟。
  2. 在 10:00 时,人为使队列达到满载状态,模拟繁忙情况。
  3. 当队列恢复到可处理状态后,任务计划在 10:01 执行。
  4. 观察到后续的执行时间变为 11:01 和 12:01,而不是预期的 11:00 和 12:00。

附带问题

另一个问题是 request_key 中包含了 due 信息。在任务重试时,request_key 的值会改变,这与注释中提到的“重试同一个槽位”的预期行为相矛盾。这可能导致任务调度不按预期进行,因为改变了的 request_key 可能会导致系统无法识别和关联到同一任务的不同重试请求。

期望与建议

针对上述问题,期望的解决方案是只将本次触发延后,而不是改变后续所有调度的执行时间。建议可以单独保存重试时间,或者在实际成功执行任务后,根据原始的 due 时间来计算下一次的执行槽位。此外,为了确保系统的稳定性和可预测性,建议补充针对 Busy 错误路径的测试用例,以验证修复后的逻辑是否正确实现并满足预期行为。

通过实施这些建议的更改,KernelSU 解决方案中的调度系统将能够更准确地处理繁忙情况,保证任务按照预期的时间执行,同时保持 request_key 的稳定性,确保任务的重试能够正确地与原始任务关联。这不仅能够提高系统的可靠性,还能增强用户体验。