初始化提交
This commit is contained in:
74
test/services/test_state.py
Normal file
74
test/services/test_state.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from app.services.state import RedisState
|
||||
|
||||
|
||||
class _FakeRedis:
|
||||
def __init__(self, batches):
|
||||
self.batches = batches
|
||||
self.data = {}
|
||||
for key in [key for batch in batches for key in batch]:
|
||||
index = int(key.decode("utf-8").split(":")[-1])
|
||||
self.data[key] = {
|
||||
b"task_id": key,
|
||||
b"state": b"1",
|
||||
b"progress": str(index).encode("utf-8"),
|
||||
}
|
||||
|
||||
def scan(self, cursor, count):
|
||||
batch_index = int(cursor)
|
||||
next_cursor = batch_index + 1
|
||||
if next_cursor >= len(self.batches):
|
||||
next_cursor = 0
|
||||
return next_cursor, self.batches[batch_index]
|
||||
|
||||
def hgetall(self, key):
|
||||
return self.data[key]
|
||||
|
||||
|
||||
class TestRedisState(unittest.TestCase):
|
||||
def _build_state(self, batch_sizes):
|
||||
keys = [f"task:{i}".encode("utf-8") for i in range(sum(batch_sizes))]
|
||||
batches = []
|
||||
offset = 0
|
||||
for batch_size in batch_sizes:
|
||||
batches.append(keys[offset : offset + batch_size])
|
||||
offset += batch_size
|
||||
|
||||
state = RedisState.__new__(RedisState)
|
||||
state._redis = _FakeRedis(batches)
|
||||
return state
|
||||
|
||||
def test_get_all_tasks_paginates_across_scan_batches(self):
|
||||
"""
|
||||
Redis SCAN 分批返回 key 时,分页切片必须按当前批次起始位置计算。
|
||||
|
||||
这个用例复现 PR #890 描述的 18 条任务、page_size=10 场景:
|
||||
第一批 10 条,第二批 8 条。旧逻辑第一页会返回空列表,第二页
|
||||
只返回 2 条;修复后第一页返回 10 条,第二页返回剩余 8 条。
|
||||
"""
|
||||
state = self._build_state([10, 8])
|
||||
|
||||
first_page, first_total = state.get_all_tasks(page=1, page_size=10)
|
||||
second_page, second_total = state.get_all_tasks(page=2, page_size=10)
|
||||
|
||||
self.assertEqual(first_total, 18)
|
||||
self.assertEqual(second_total, 18)
|
||||
self.assertEqual(len(first_page), 10)
|
||||
self.assertEqual(len(second_page), 8)
|
||||
self.assertEqual(
|
||||
[task["task_id"] for task in first_page],
|
||||
[f"task:{i}" for i in range(10)],
|
||||
)
|
||||
self.assertEqual(
|
||||
[task["task_id"] for task in second_page],
|
||||
[f"task:{i}" for i in range(10, 18)],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user