Reputation: 8516
I want to run a starlette and django app in the same thread.
(Having them in same thread allows fast thread-local communication between them).
Considering that asgi apps are just coroutines, I thought this should be theoretically possible with asyncio.gather()
.
I came up with a little hack to make this work, but it has some limitations.
from uvicorn import Server, Config
configs = [Config(app1, uds='app1.sock'), Config(app2, uds='app2.sock')]
coros = [Server(c).serve() for c in configs]
await asyncio.gather(*coros)
reload
and workers
options.INFO: Started server process [86066]
INFO: Waiting for application startup.
INFO: Started server process [86066]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: Uvicorn running on unix socket app1.sock (Press CTRL+C to quit)
INFO: Application startup complete.
INFO: Uvicorn running on unix socket app2.sock (Press CTRL+C to quit)
^CINFO: Shutting down
INFO: Finished server process [86066]
^C^C^C^C^C
What's a better way to do this?
Upvotes: 6
Views: 5172
Reputation: 8516
Update - If you have a separation of paths between 2 apps, you can use this to skip starlette's middleware:
from mydjangoapp.asgi import application as django_app
ws_app = Starlette(...)
async def app(scope, receive, send):
path = scope.get("path")
chosen = ws_app
if not (path is None or path.startswith("/ws")):
chosen = django_app
return await chosen(scope, receive, send)
Silly me! Starlette supports mounting arbitrary ASGI apps, which means you can just do the following and use any ol' ASGI server from the command line.
from mydjangoapp.asgi import application as django_app
app = Starlette(...)
app.mount('/', django_app)
Upvotes: 8