Files
video-gen/video-gen-api/app/tasks/async_runner.py
T

48 lines
1.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
import os
import threading
from typing import Awaitable, TypeVar
T = TypeVar("T")
_thread_local = threading.local()
def _get_or_create_loop() -> asyncio.AbstractEventLoop:
"""
给当前进程/线程维护一个长期 event loop。
Linux prefork
每个 Celery 子进程通常单线程跑任务,这里相当于每个子进程一个长期 loop。
Windows -P threads
每个线程一个 loop,但注意 asyncpg pool 仍不适合跨线程共享;
Windows threads 模式建议继续用 NullPool 或只做本地调试。
"""
pid = os.getpid()
loop = getattr(_thread_local, "loop", None)
loop_pid = getattr(_thread_local, "pid", None)
if loop is None or loop.is_closed() or loop_pid != pid:
loop = asyncio.new_event_loop()
_thread_local.loop = loop
_thread_local.pid = pid
return loop
def run_async(coro: Awaitable[T]) -> T:
"""
Celery 同步 task 调用异步协程的统一入口。
不使用 asyncio.run(),避免每个 task 结束时关闭 event loop。
"""
loop = _get_or_create_loop()
return loop.run_until_complete(coro)
def close_loop() -> None:
loop = getattr(_thread_local, "loop", None)
if loop is not None and not loop.is_closed():
loop.close()
_thread_local.loop = None
_thread_local.pid = None