|
| 1 | +import asyncio |
1 | 2 | import logging |
2 | 3 | import uuid |
3 | | -from typing import Tuple |
| 4 | +from contextlib import asynccontextmanager |
| 5 | +from typing import Any, Tuple |
4 | 6 |
|
| 7 | +import httpx |
5 | 8 | import pytest |
6 | 9 | import sqlalchemy as sa |
| 10 | +import uvicorn |
7 | 11 | from fastapi import FastAPI |
8 | 12 | from fastapi.testclient import TestClient |
9 | 13 |
|
10 | 14 | # Public API |
11 | | -from dbos import DBOS |
| 15 | +from dbos import DBOS, ConfigFile |
12 | 16 |
|
13 | 17 | # Private API because this is a unit test |
14 | 18 | from dbos._context import assert_current_dbos_context |
@@ -159,6 +163,48 @@ def test_endpoint(var1: str, var2: str) -> dict[str, str]: |
159 | 163 | assert workflow_handles[0].get_result() == ("a", wfuuid) |
160 | 164 |
|
161 | 165 |
|
| 166 | +@pytest.mark.asyncio |
| 167 | +async def test_custom_lifespan( |
| 168 | + config: ConfigFile, cleanup_test_databases: None |
| 169 | +) -> None: |
| 170 | + resource = None |
| 171 | + port = 8000 |
| 172 | + |
| 173 | + @asynccontextmanager |
| 174 | + async def lifespan(app: FastAPI) -> Any: |
| 175 | + nonlocal resource |
| 176 | + resource = 1 |
| 177 | + yield |
| 178 | + resource = None |
| 179 | + |
| 180 | + app = FastAPI(lifespan=lifespan) |
| 181 | + |
| 182 | + DBOS.destroy() |
| 183 | + DBOS(fastapi=app, config=config) |
| 184 | + |
| 185 | + @app.get("/") |
| 186 | + @DBOS.workflow() |
| 187 | + async def resource_workflow() -> Any: |
| 188 | + return {"resource": resource} |
| 189 | + |
| 190 | + uvicorn_config = uvicorn.Config( |
| 191 | + app=app, host="127.0.0.1", port=port, log_level="error" |
| 192 | + ) |
| 193 | + server = uvicorn.Server(config=uvicorn_config) |
| 194 | + |
| 195 | + # Run server in background task |
| 196 | + server_task = asyncio.create_task(server.serve()) |
| 197 | + await asyncio.sleep(0.2) # Give server time to start |
| 198 | + |
| 199 | + async with httpx.AsyncClient() as client: |
| 200 | + r = await client.get(f"http://127.0.0.1:{port}") |
| 201 | + assert r.json()["resource"] == 1 |
| 202 | + |
| 203 | + server.should_exit = True |
| 204 | + await server_task |
| 205 | + assert resource is None |
| 206 | + |
| 207 | + |
162 | 208 | def test_stacked_decorators_wf(dbos_fastapi: Tuple[DBOS, FastAPI]) -> None: |
163 | 209 | dbos, app = dbos_fastapi |
164 | 210 | client = TestClient(app) |
|
0 commit comments