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