2022-05-31 17:56:37 +00:00
|
|
|
|
|
|
|
import asyncio
|
|
|
|
import threading
|
|
|
|
import time
|
|
|
|
|
2022-05-31 20:53:20 +00:00
|
|
|
def loop_thread(loop, exception_handler):
|
|
|
|
if hasattr(exception_handler, '__call__'):
|
|
|
|
loop.set_exception_handler(lambda loop, context: exception_handler(loop, context, None))
|
|
|
|
loop.run_forever()
|
|
|
|
|
|
|
|
def future_handler(future, loop, exception_handler, response):
|
|
|
|
try:
|
|
|
|
future.result()
|
|
|
|
return None
|
|
|
|
except Exception as error:
|
|
|
|
if hasattr(exception_handler, '__call__'):
|
|
|
|
exception_handler(loop, error, response)
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
#just log in console the error to call attention
|
|
|
|
print("Uncaught Exception: %s" % str(error))
|
|
|
|
if response != None:
|
|
|
|
response.write_status(500).end("Internal Error")
|
|
|
|
finally:
|
|
|
|
return
|
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
class Loop:
|
2022-05-31 20:53:20 +00:00
|
|
|
def __init__(self, exception_handler=None):
|
2022-05-31 17:56:37 +00:00
|
|
|
self.loop = asyncio.new_event_loop()
|
2022-05-31 20:53:20 +00:00
|
|
|
if hasattr(exception_handler, '__call__'):
|
|
|
|
self.exception_handler = exception_handler
|
|
|
|
self.loop.set_exception_handler(lambda loop, context: exception_handler(loop, context, None))
|
|
|
|
else:
|
|
|
|
self.exception_handler = None
|
|
|
|
|
2022-05-31 17:56:37 +00:00
|
|
|
asyncio.set_event_loop(self.loop)
|
|
|
|
self.loop_thread = None
|
|
|
|
|
|
|
|
def start(self):
|
2022-05-31 20:53:20 +00:00
|
|
|
self.loop_thread = threading.Thread(target=loop_thread, args=(self.loop,self.exception_handler), daemon=True)
|
2022-05-31 17:56:37 +00:00
|
|
|
self.loop_thread.start()
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
#stop loop
|
|
|
|
self.loop.call_soon_threadsafe(self.loop.stop)
|
|
|
|
#wait loop thread to stops
|
|
|
|
self.loop_thread.join()
|
|
|
|
# Find all running tasks in main thread:
|
|
|
|
pending = asyncio.all_tasks(self.loop)
|
|
|
|
# Run loop until tasks done
|
|
|
|
self.loop.run_until_complete(asyncio.gather(*pending))
|
|
|
|
|
2022-05-31 20:53:20 +00:00
|
|
|
def run_async(self, task, response=None):
|
|
|
|
future = asyncio.run_coroutine_threadsafe(task, self.loop)
|
|
|
|
future.add_done_callback(lambda f: future_handler(f, self.loop, self.exception_handler, response))
|
|
|
|
return future
|
2022-06-01 23:00:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# if sys.version_info >= (3, 11)
|
|
|
|
# with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
|
|
|
|
# runner.run(main())
|
|
|
|
# else:
|
|
|
|
# uvloop.install()
|
|
|
|
# asyncio.run(main())
|