Spaces:
Running
Running
File size: 2,005 Bytes
b9d11ff | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | """后台任务的所属启动、停止信号与取消安全等待(保留周期任务导出名)。"""
import asyncio
import logging
logger = logging.getLogger("ComfyUI-Ranking.PeriodicTasks")
def start_periodic_task(state, name, factory):
current = getattr(state, name + "_worker", None)
if current is not None and not current.done():
return current
stop = asyncio.Event()
coroutine = factory(stop)
try:
task = asyncio.create_task(coroutine)
except BaseException:
coroutine.close()
raise
setattr(state, name + "_stop", stop)
setattr(state, name + "_worker", task)
def consume(completed):
if not completed.cancelled():
error = completed.exception()
if error is not None:
logger.warning("后台任务结束异常: task=%s | error_type=%s", name, type(error).__name__)
task.add_done_callback(consume)
return task
def request_periodic_stop(state, names):
tasks = []
for name in names:
stop = getattr(state, name + "_stop", None)
if stop is not None:
stop.set()
task = getattr(state, name + "_worker", None)
if task is not None:
tasks.append(task)
return tasks
async def wait_periodic_tasks(tasks):
cancelled = None
for task in tasks:
while not task.done():
try:
await asyncio.shield(task)
except asyncio.CancelledError as error:
# worker自身取消与关闭等待者取消分别处理。
if asyncio.current_task().cancelling() or not task.cancelled():
cancelled = error
except Exception:
break
if not task.cancelled():
# 业务异常已有所属回调诊断,不阻止其它任务收尾和最终同步。
task.exception()
if cancelled is not None:
raise cancelled
|