human/utils/async_task_queue.py

71 lines
2.2 KiB
Python
Raw Normal View History

#encoding = utf8
import asyncio
2024-11-07 12:43:46 +00:00
import logging
from queue import Queue
import threading
2024-11-07 12:43:46 +00:00
logger = logging.getLogger(__name__)
class AsyncTaskQueue:
2024-11-07 00:26:03 +00:00
def __init__(self, name, work_num=1):
2024-11-07 12:43:46 +00:00
self._queue = Queue()
2024-10-14 10:20:55 +00:00
self._worker_num = work_num
self._current_worker_num = work_num
2024-11-07 00:26:03 +00:00
self._name = name
self._thread = threading.Thread(target=self._run_loop, name=name)
self._thread.start()
2024-10-14 10:20:55 +00:00
self.__loop = None
def _run_loop(self):
2024-11-07 12:43:46 +00:00
logging.info(f'{self._name}, _run_loop')
2024-10-14 10:20:55 +00:00
self.__loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.__loop)
self._tasks = [self.__loop.create_task(self._worker()) for _ in range(self._worker_num)]
2024-11-07 12:43:46 +00:00
try:
self.__loop.run_forever()
finally:
logging.info(f'{self._name}, exit run')
self.__loop.run_until_complete(asyncio.gather(*asyncio.all_tasks(self.__loop)))
2024-10-14 10:20:55 +00:00
self.__loop.close()
2024-11-07 12:43:46 +00:00
logging.info(f'{self._name}, close loop')
async def _worker(self):
2024-11-07 12:43:46 +00:00
logging.info(f'{self._name}, _worker')
2024-10-13 14:49:17 +00:00
while True:
2024-11-07 12:43:46 +00:00
try:
task = self._queue.get()
if task is None: # None as a stop signal
break
func, *args = task # Unpack task
if func is None: # None as a stop signal
break
await func(*args) # Execute async function
except Exception as e:
2024-11-07 23:27:00 +00:00
logging.error(f'{self._name} error: {e}')
2024-11-07 12:43:46 +00:00
finally:
self._queue.task_done()
2024-10-14 10:20:55 +00:00
2024-11-07 12:43:46 +00:00
logging.info(f'{self._name}, _worker finish')
2024-11-05 11:40:03 +00:00
self._current_worker_num -= 1
2024-10-14 10:20:55 +00:00
if self._current_worker_num == 0:
2024-11-07 12:43:46 +00:00
self.__loop.call_soon_threadsafe(self.__loop.stop)
2024-10-14 10:20:55 +00:00
def add_task(self, func, *args):
2024-11-07 12:43:46 +00:00
self._queue.put((func, *args))
2024-10-14 10:20:55 +00:00
def stop_workers(self):
for _ in range(self._worker_num):
2024-11-05 11:40:03 +00:00
self.add_task(None) # Send stop signal
2024-10-19 10:47:34 +00:00
def clear(self):
while not self._queue.empty():
2024-11-05 11:40:03 +00:00
self._queue.get_nowait()
2024-10-19 10:47:34 +00:00
self._queue.task_done()
def stop(self):
2024-10-14 10:20:55 +00:00
self.stop_workers()
2024-11-07 12:43:46 +00:00
self._thread.join()