fix: 批量删除任务完成前等待所有进度更新的异步回调完成

收集 run_coroutine_threadsafe 返回的 Future,在标记任务完成前
通过 asyncio.gather 等待所有进度更新回调执行完毕,避免任务
状态提前跳到 completed 而进度数据尚未写入 Redis 的竞态问题。
This commit is contained in:
fawney19
2026-03-09 02:52:38 +08:00
parent fd32597015
commit 654ce89541
2 changed files with 115 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ import asyncio
import json
import uuid
from collections.abc import Callable
from concurrent.futures import Future
import redis.asyncio as aioredis
from sqlalchemy import delete as sa_delete
@@ -232,18 +233,33 @@ async def _run_batch_delete(
# 从工作线程安全地触发 Redis 进度更新
loop = asyncio.get_running_loop()
progress_futures: list[Future[object]] = []
def on_progress(current: int) -> None:
try:
asyncio.run_coroutine_threadsafe(
future = asyncio.run_coroutine_threadsafe(
_update_task_field(task_id, r=r, deleted=current), loop
)
progress_futures.append(future)
except RuntimeError:
pass
try:
affected = await asyncio.to_thread(_sync_delete, provider_id, key_ids, on_progress)
if progress_futures:
results = await asyncio.gather(
*(asyncio.wrap_future(f) for f in progress_futures),
return_exceptions=True,
)
for exc in results:
if isinstance(exc, Exception):
logger.debug(
"[BATCH_DELETE_TASK] progress update failed task={}: {}",
task_id,
exc,
)
# 副作用(缓存失效等)是异步操作,在事件循环中执行
if affected > 0:
try: