Skip to content

invoke_startup() is not run in some conditions, e.g. gunicorn/uvicorn workers, breaking lots of things #1955

@Rik-de-Kort

Description

@Rik-de-Kort

In the past (pre-september 14, #1809) I had a running deployment of Datasette on Azure WebApps by emulating the call in cli.py to Gunicorn: gunicorn -w 2 -k uvicorn.workers.UvicornWorker app:app.

My most recent deployment, however, fails loudly by shouting that Datasette.invoke_startup() was not called. It does not seem to be possible to call invoke_startup when running using a uvicorn command directly like this (I've reproduced this locally using uvicorn). Two candidates that I have tried:

  • Uvicorn has a --factory option, but the app factory has to be synchronous, so no await invoke_startup there
  • asyncio.get_event_loop().run_until_complete is also not an option because uvicorn already has the event loop running.

One additional option is:

  • Use Gunicorn's server hooks to call invoke_startup. These are also synchronous, but I might be able to get ahead of the event loop starting here.

In my current deployment setup, it does not appear to be possible to use datasette serve directly, so I'm stuck either

  • Trying to rework my complete deployment setup, for instance, using Azure functions as described here)
  • Or dig into the ASGI spec and write a wrapper for the sole purpose of launching Datasette using a direct Uvicorn invocation.

Questions for the maintainers:

  • Is this intended behaviour/will not support/etc.? If so, I'd be happy to add a PR with a couple lines in the documentation.
  • if this is not intended behaviour, what is a good way to fix it? I could have a go at the ASGI spec thing (I think the Azure Functions thing is related) and provide a PR with the wrapper here, but I'm all ears!

Almost forgot, minimal reproducer:

from datasette import Datasette

ds = Datasette(files=['./global-power-plants.db'])]
app = ds.app()

Save as app.py in the same folder as global-power-plants.db, and then try running
uvicorn app:app.

Opening the resulting Datasette instance in the browser will show the error message.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions