Dev Aggarwal
Dev Aggarwal

Reputation: 8516

Run multiple asgi apps in same thread with uvicorn

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)

  1. Doesn't support reload and workers options.
  2. Ctrl+C only works for one app.
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

Answers (1)

Dev Aggarwal
Dev Aggarwal

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

Related Questions