-
-
Notifications
You must be signed in to change notification settings - Fork 931
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Revert "Support lifespan state (#2060)" This reverts commit da6461b. * new implementation * Deprecate `on_startup` and `on_shutdown` events * Rename `events.md` by `lifespan.md` --------- Co-authored-by: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>
- Loading branch information
Showing
10 changed files
with
152 additions
and
174 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 was deleted.
Oops, something went wrong.
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 |
---|---|---|
@@ -0,0 +1,91 @@ | ||
|
||
Starlette applications can register a lifespan handler for dealing with | ||
code that needs to run before the application starts up, or when the application | ||
is shutting down. | ||
|
||
```python | ||
import contextlib | ||
|
||
from starlette.applications import Starlette | ||
|
||
|
||
@contextlib.asynccontextmanager | ||
async def lifespan(app): | ||
async with some_async_resource(): | ||
print("Run at startup!") | ||
yield | ||
print("Run on shutdown!") | ||
|
||
|
||
routes = [ | ||
... | ||
] | ||
|
||
app = Starlette(routes=routes, lifespan=lifespan) | ||
``` | ||
|
||
Starlette will not start serving any incoming requests until the lifespan has been run. | ||
|
||
The lifespan teardown will run once all connections have been closed, and | ||
any in-process background tasks have completed. | ||
|
||
Consider using [`anyio.create_task_group()`](https://anyio.readthedocs.io/en/stable/tasks.html) | ||
for managing asynchronous tasks. | ||
|
||
## Lifespan State | ||
|
||
The lifespan has the concept of `state`, which is a dictionary that | ||
can be used to share the objects between the lifespan, and the requests. | ||
|
||
```python | ||
import contextlib | ||
from typing import TypedDict | ||
|
||
import httpx | ||
from starlette.applications import Starlette | ||
from starlette.responses import PlainTextResponse | ||
from starlette.routing import Route | ||
|
||
|
||
class State(TypedDict): | ||
http_client: httpx.AsyncClient | ||
|
||
|
||
@contextlib.asynccontextmanager | ||
async def lifespan(app: Starlette) -> State: | ||
async with httpx.AsyncClient() as client: | ||
yield {"http_client": client} | ||
|
||
|
||
async def homepage(request): | ||
client = request.state.http_client | ||
response = await client.get("https://www.example.com") | ||
return PlainTextResponse(response.text) | ||
|
||
|
||
app = Starlette( | ||
lifespan=lifespan, | ||
routes=[Route("/", homepage)] | ||
) | ||
``` | ||
|
||
The `state` received on the requests is a **shallow** copy of the state received on the | ||
lifespan handler. | ||
|
||
## Running lifespan in tests | ||
|
||
You should use `TestClient` as a context manager, to ensure that the lifespan is called. | ||
|
||
```python | ||
from example import app | ||
from starlette.testclient import TestClient | ||
|
||
|
||
def test_homepage(): | ||
with TestClient(app) as client: | ||
# Application's lifespan is called on entering the block. | ||
response = client.get("/") | ||
assert response.status_code == 200 | ||
|
||
# And the lifespan's teardown is run when exiting the block. | ||
``` |
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
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
Oops, something went wrong.