From 6e7c641fd4965045f051ae9b375c5eab4da66f63 Mon Sep 17 00:00:00 2001 From: lanceyq <1982376970@qq.com> Date: Mon, 30 Mar 2026 18:46:25 +0800 Subject: [PATCH] [fix] Remove duplicate creations --- api/app/tasks.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/api/app/tasks.py b/api/app/tasks.py index 73b001e2..4928ca7f 100644 --- a/api/app/tasks.py +++ b/api/app/tasks.py @@ -101,10 +101,11 @@ def get_sync_redis_client() -> Optional[redis.StrictRedis]: def set_asyncio_event_loop(): - """Set the asyncio event loop for the current thread. + """Ensure an open asyncio event loop exists for the current thread. - Always creates a fresh event loop to avoid 'Event loop is closed' errors - caused by stale httpx.AsyncClient objects from previous task runs. + Reuses the existing event loop if one is available and still open. + Creates and installs a new event loop only when the current one is + closed or missing (e.g. after ``_shutdown_loop_gracefully``). """ try: loop = asyncio.get_event_loop() @@ -122,6 +123,9 @@ def _shutdown_loop_gracefully(loop: asyncio.AbstractEventLoop): This prevents 'RuntimeError: Event loop is closed' from httpx.AsyncClient.__del__ by giving pending aclose() coroutines a chance to run before the loop is discarded. + + Note: This only tears down the given loop. Callers that need a fresh event + loop afterwards should use ``set_asyncio_event_loop()`` explicitly. """ try: # Cancel and collect all remaining tasks @@ -136,9 +140,6 @@ def _shutdown_loop_gracefully(loop: asyncio.AbstractEventLoop): pass finally: loop.close() - # Set a new event loop so subsequent tasks get a fresh one - new_loop = asyncio.new_event_loop() - asyncio.set_event_loop(new_loop) @celery_app.task(name="tasks.process_item")