[Bug]: Redis SCAN 分页顺序不稳定可能漏掉跨平台发布恢复任务

Author: shuyan-codeCreated Sep 27, 2026Updated Sep 28, 2026

问题描述 | Problem Statement

在 Redis 模式下,RedisState.get_all_tasks(page, page_size) 每调用一次都会从头执行一次 SCAN,然后按这次遍历的返回顺序切页(state.py)。SCAN 没有稳定排序保证,任务增删时也可能返回重复键。两个分页请求若看到不同的遍历顺序,就可能重复展示某个任务、漏掉另一个任务。

这个问题还会影响启动后的跨平台发布恢复:recover_interrupted_cross_posts() 逐页调用 get_all_tasks。若漏掉一条遗留的 pending/processing 记录,该任务可能继续停留在“进行中”,与该函数要解决的状态相反。

一个不依赖具体 Redis 哈希顺序的测试场景:3 条任务、page_size=2。第一页扫描顺序为 A,B,C,返回 A,B;第二次独立扫描顺序为 C,A,B,按偏移返回 B。最终 B 重复、C 遗漏。当前切片索引的修复(PR #890)解决了单次扫描的批次偏移计算,但不保证跨调用的顺序。

建议的解决方案 | Proposed Solution

  1. 恢复流程先修正: 在一次扫描中收集候选 task ID,并用 seen 去重;基于同一批 ID 读取及更新状态,不要靠多次独立扫描的页码推进。对扫描期间新增的任务,可在下一次启动/恢复周期处理。
  2. 列表分页定义稳定顺序: 为 Redis 任务维护按创建时间与 task ID 排序的索引(如 ZSET),分页从索引取 ID 后批量读取 Hash;删除任务时同步移除索引项。对旧任务提供一次性回填或兼容路径。若暂不引入索引,至少先完整扫描、去重并按明确键排序后再切页,作为正确性优先的过渡方案。
  3. 增加回归测试:模拟两次 SCAN 返回不同顺序及重复键,验证列表不重不漏;验证恢复逻辑对每条遗留的活动发布状态都处理一次。并发增删时注明一致性边界。

这与现有视频生成任务列表和跨平台发布状态恢复直接相关,不需要新增业务流程。

Source: harry0703/MoneyPrinterTurbo