Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove on_startup, on_shutdown, event system and deprecated lifespans #2068

Closed
wants to merge 4 commits into from

Conversation

adriangb
Copy link
Member

@adriangb adriangb commented Mar 5, 2023

#2067

Close to 500 LOC removed. That's ~ 1/20th of the codebase.

@adriangb adriangb changed the title Explore removing on_startup and on_shutdown Remove on_startup, on_shutdown, event system and deprecated lifespans Mar 7, 2023
@euri10
Copy link
Member

euri10 commented Mar 7, 2023

what do you think about adding a little "migration" guide like:

you used to do this:

async def startup():
	await open_some_ressource()
async def shutdown():
	await close_some_ressource()
app = Starlette(
	routes=routes,
	on_startup=[startup],
	on_shutdown=[shutdown]
)

now do this:

@asynccontextmanager
async def lifespan():
	try:
		await open_some_ressource()
		yield
	finally:
		await close_some_ressource()
app = Starlette(
    routes=routes,
	lifespan=lifespan
)

or it's too obvious ?

@adriangb
Copy link
Member Author

adriangb commented Mar 7, 2023

I don't think it's too obvious, I agree we should add it. But we should probably do the same for all of the things we are deprecating / removing. Maybe it's time to start a v1migration.md doc that I can add to in this PR?

Comment on lines +50 to +51
await database.connect()
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't those 2 lines be interverted ?


A single lifespan `asynccontextmanager` handler can be used instead of
separate startup and shutdown handlers:
Starlette will not start serving any incoming requests until the lifespan has been run.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean uvicorn right ?

Comment on lines +32 to 35
The lifespan can also accept a `state` argument, which is a dictionary
that can be used to share the objects between the startup and shutdown handlers,
and the requests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to me that this becomes outdated since there wont be startup and shutdown handlers

@Kludex Kludex added this to the Version 1.0 milestone Mar 7, 2023
@adriangb adriangb mentioned this pull request Mar 10, 2023
11 tasks
@gnat
Copy link

gnat commented Mar 11, 2023

So, what do we do now? This is a breaking change.

@asynccontextmanager
async def lifespan():
	try:
		await open_some_ressource()
		yield
	finally:
		await close_some_ressource()
app = Starlette(
    routes=routes,
	lifespan=lifespan
)

This is really not obvious.

Is there any way to get the equivalent functionality of on_startup, on_shutdown more intuitively?

The DX of being able to just specify a function for these important events is a good thing.

@gnat
Copy link

gnat commented Mar 11, 2023

Side "meta" note, what is with all the breaking PR's this year? Is the plan to force everyone to completely re-learn Starlette and re-write their apps for 1.0... 🤷 What makes this more egregious is the proposed patterns have worse DX

@tomchristie

@adriangb
Copy link
Member Author

Your example is very contrived, I seriously doubt anyone is doing that.

@gnat
Copy link

gnat commented Mar 11, 2023

Not my code, re: #2068 (comment)

@adriangb
Copy link
Member Author

Misread. Thought you were yielding a something, which, indeed, would be breaking, but like I said very contrived.

We have documentation for this. And there are good reasons why this approach is much better than two separate functions. I’m afraid I do not agree that it is very non-obvious how to use.

@gnat
Copy link

gnat commented Mar 11, 2023

@@ -3,6 +3,7 @@ Starlette includes an application class `Starlette` that nicely ties together al
its other functionality.

```python
from contextlib import asyccontextmanager
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asyccontextmanager should be asynccontextmanager

@@ -25,8 +26,10 @@ async def websocket_endpoint(websocket):
await websocket.send_text('Hello, websocket!')
await websocket.close()

def startup():
@asyccontextmanager
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asyccontextmanager should be asynccontextmanager

@adriangb
Copy link
Member Author

@Kludex
Copy link
Member

Kludex commented Mar 11, 2023

Decisions can be reversed until 1.0... But a better place to talk about it would be the discussion that was taken. I'm on my phone right now.

@Kludex
Copy link
Member

Kludex commented Mar 11, 2023

The idea of deprecating things now is to avoid doing so on 1.0.

Feedback is always welcome, and if we made a mistake, we can revert decisions.

@gnat
Copy link

gnat commented Mar 11, 2023

For people reading this PR, FastAPI went official with this in 0.93.0, only a few days ago: #2067 (comment)

Totally fair with the discussion that happened in: #2067 That's fine. The cat is out of the bag at this point.

Gonna go make the changes to my Starlette apps now.

@Kludex
Copy link
Member

Kludex commented Mar 11, 2023

Cool.

But in any case, we are always open to take decisions back if they make sense. We don't want to harm users, and I think we try to always be transparent here.

@dineshbvadhia
Copy link

@Kludex
As of today, the FastApi/Starlette lifespan feature results in an "async generators are unimplemented" error when compiling with mypyc. Until mypyc supports async generators, the on_startup/on_shutdown feature should be retained as it passes with mypyc.

@Kludex
Copy link
Member

Kludex commented Oct 13, 2023

@Kludex As of today, the FastApi/Starlette lifespan feature results in an "async generators are unimplemented" error when compiling with mypyc. Until mypyc supports async generators, the on_startup/on_shutdown feature should be retained as it passes with mypyc.

Ref.: mypyc/mypyc#868

@Kludex
Copy link
Member

Kludex commented Dec 23, 2023

I've applied this on #2384, and given co-author to @adriangb there. FYI

@Kludex Kludex closed this Dec 23, 2023
@graingert
Copy link
Member

@Kludex As of today, the FastApi/Starlette lifespan feature results in an "async generators are unimplemented" error when compiling with mypyc. Until mypyc supports async generators, the on_startup/on_shutdown feature should be retained as it passes with mypyc.

You don't need to use async generators to create an async context manager you can just manually implement __aenter__ and __aexit__ on a class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants