-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2616fc3
commit 528f686
Showing
3 changed files
with
36 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,26 @@ | ||
# taken from https://github.com/encode/uvicorn/discussions/1103#discussioncomment-6187606 | ||
|
||
import asyncio | ||
import threading | ||
import time | ||
|
||
import uvicorn | ||
|
||
# this code is taken from freqtrade | ||
|
||
|
||
def asyncio_setup() -> None: # pragma: no cover | ||
# Set eventloop for win32 setups | ||
# Reverts a change done in uvicorn 0.15.0 - which now sets the eventloop | ||
# via policy. | ||
import sys | ||
|
||
if sys.version_info >= (3, 8) and sys.platform == "win32": | ||
import asyncio | ||
import selectors | ||
|
||
selector = selectors.SelectSelector() | ||
loop = asyncio.SelectorEventLoop(selector) | ||
asyncio.set_event_loop(loop) | ||
|
||
|
||
class UvicornServer(uvicorn.Server): | ||
""" | ||
Multithreaded server - as found in https://github.com/encode/uvicorn/issues/742 | ||
|
||
Removed install_signal_handlers() override based on changes from this commit: | ||
https://github.com/encode/uvicorn/commit/ce2ef45a9109df8eae038c0ec323eb63d644cbc6 | ||
class ThreadedUvicorn: | ||
def __init__(self, config: uvicorn.Config): | ||
self.server = uvicorn.Server(config) | ||
self.thread = threading.Thread(daemon=True, target=self.server.run) | ||
|
||
Cannot rely on asyncio.get_event_loop() to create new event loop because of this check: | ||
https://github.com/python/cpython/blob/4d7f11e05731f67fd2c07ec2972c6cb9861d52be/Lib/asyncio/events.py#L638 | ||
Fix by overriding run() and forcing creation of new event loop if uvloop is available | ||
""" | ||
|
||
def run(self, sockets=None): | ||
import asyncio | ||
|
||
""" | ||
Parent implementation calls self.config.setup_event_loop(), | ||
but we need to create uvloop event loop manually | ||
""" | ||
try: | ||
import uvloop # pyright: ignore[reportMissingImports] | ||
except ImportError: # pragma: no cover | ||
asyncio_setup() | ||
else: | ||
asyncio.set_event_loop(uvloop.new_event_loop()) | ||
try: | ||
loop = asyncio.get_running_loop() | ||
except RuntimeError: | ||
# When running in a thread, we'll not have an eventloop yet. | ||
loop = asyncio.new_event_loop() | ||
|
||
loop.run_until_complete(self.serve(sockets=sockets)) | ||
|
||
def run_in_thread(self): | ||
self.thread = threading.Thread(target=self.run) | ||
def start(self): | ||
self.thread.start() | ||
while not self.started: | ||
time.sleep(1e-3) | ||
asyncio.run(self.wait_for_started()) | ||
|
||
async def wait_for_started(self): | ||
while not self.server.started: | ||
await asyncio.sleep(0.1) | ||
|
||
def cleanup(self): | ||
self.should_exit = True | ||
self.thread.join() | ||
def stop(self): | ||
if self.thread.is_alive(): | ||
self.server.should_exit = True | ||
while self.thread.is_alive(): | ||
continue |