Skip to content

Commit 2ea489c

Browse files
committed
@sanderegg review: config error
1 parent 43cc5a7 commit 2ea489c

File tree

4 files changed

+47
-17
lines changed

4 files changed

+47
-17
lines changed

packages/service-library/src/servicelib/fastapi/lifespan_utils.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
11
from collections.abc import AsyncIterator
22
from typing import Protocol
33

4+
from common_library.errors_classes import OsparcErrorMixin
45
from fastapi import FastAPI
56
from fastapi_lifespan_manager import LifespanManager, State
67

78

9+
class LifespanError(OsparcErrorMixin, RuntimeError): ...
10+
11+
12+
class LifespanOnStartupError(LifespanError):
13+
msg_template = "Failed during startup of {module}"
14+
15+
16+
class LifespanOnShutdownError(LifespanError):
17+
msg_template = "Failed during shutdown of {module}"
18+
19+
820
class LifespanGenerator(Protocol):
9-
def __call__(self, app: FastAPI) -> AsyncIterator["State"]:
10-
...
21+
def __call__(self, app: FastAPI) -> AsyncIterator["State"]: ...
1122

1223

1324
def combine_lifespans(*generators: LifespanGenerator) -> LifespanManager:

packages/service-library/src/servicelib/fastapi/postgres_lifespan.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from sqlalchemy.ext.asyncio import AsyncEngine
99

1010
from ..db_asyncpg_utils import create_async_engine_and_database_ready
11+
from .lifespan_utils import LifespanOnStartupError
1112

1213
_logger = logging.getLogger(__name__)
1314

@@ -20,6 +21,10 @@ class PostgresLifespanStateKeys(str, Enum):
2021
POSTGRES_ASYNC_ENGINE = "postgres.async_engine"
2122

2223

24+
class PostgresConfigurationError(LifespanOnStartupError):
25+
msg_template = "Invalid postgres settings [={pg_settings}] on startup. Note that postgres cannot be disabled using settings"
26+
27+
2328
@postgres_lifespan_manager.add
2429
async def setup_postgres_database(_, state: State) -> AsyncIterator[State]:
2530

@@ -30,8 +35,7 @@ async def setup_postgres_database(_, state: State) -> AsyncIterator[State]:
3035
]
3136

3237
if pg_settings is None or not isinstance(pg_settings, PostgresSettings):
33-
msg = f"Invalid {pg_settings=} on startup. Postgres cannot be disabled using settings"
34-
raise RuntimeError(msg)
38+
raise PostgresConfigurationError(pg_settings=pg_settings, module="postgres")
3539

3640
assert isinstance(pg_settings, PostgresSettings) # nosec
3741

packages/service-library/tests/fastapi/test_lifespan_utils.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111

1212
import pytest
1313
from asgi_lifespan import LifespanManager as ASGILifespanManager
14-
from common_library.errors_classes import OsparcErrorMixin
1514
from fastapi import FastAPI
1615
from fastapi_lifespan_manager import LifespanManager, State
1716
from pytest_mock import MockerFixture
1817
from pytest_simcore.helpers.logging_tools import log_context
19-
from servicelib.fastapi.lifespan_utils import combine_lifespans
18+
from servicelib.fastapi.lifespan_utils import (
19+
LifespanOnShutdownError,
20+
LifespanOnStartupError,
21+
combine_lifespans,
22+
)
2023

2124

2225
async def test_multiple_lifespan_managers(capsys: pytest.CaptureFixture):
@@ -161,17 +164,6 @@ async def setup_rpc_server(app: FastAPI, state: State) -> AsyncIterator[State]:
161164
# <- postgres_sync_engine done (1ms)
162165

163166

164-
class LifespanError(OsparcErrorMixin, RuntimeError): ...
165-
166-
167-
class LifespanOnStartupError(LifespanError):
168-
msg_template = "Failed during startup of {module}"
169-
170-
171-
class LifespanOnShutdownError(LifespanError):
172-
msg_template = "Failed during shutdown of {module}"
173-
174-
175167
@pytest.fixture
176168
def failing_lifespan_manager(mocker: MockerFixture):
177169
startup_step = mocker.MagicMock()

packages/service-library/tests/fastapi/test_postgres_lifespan.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from pytest_simcore.helpers.monkeypatch_envs import setenvs_from_dict
1818
from pytest_simcore.helpers.typing_env import EnvVarsDict
1919
from servicelib.fastapi.postgres_lifespan import (
20+
PostgresConfigurationError,
2021
PostgresLifespanStateKeys,
2122
postgres_lifespan_manager,
2223
)
@@ -147,3 +148,25 @@ async def my_faulty_setup(app: FastAPI, state: State) -> AsyncIterator[State]:
147148
# Verify that the engine was disposed even if error happend
148149
async_engine: Any = mock_create_async_engine_and_database_ready.return_value
149150
async_engine.dispose.assert_called_once()
151+
152+
153+
async def test_setup_postgres_database_with_empty_pg_settings(
154+
is_pdb_enabled: bool,
155+
):
156+
async def my_app_settings(app: FastAPI) -> AsyncIterator[State]:
157+
yield {PostgresLifespanStateKeys.POSTGRES_SETTINGS: None}
158+
159+
app_lifespan_manager = LifespanManager()
160+
app_lifespan_manager.add(my_app_settings)
161+
162+
app_lifespan_manager.include(postgres_lifespan_manager)
163+
164+
app = FastAPI(lifespan=app_lifespan_manager)
165+
166+
with pytest.raises(PostgresConfigurationError, match="postgres cannot be disabled"):
167+
async with ASGILifespanManager(
168+
app,
169+
startup_timeout=None if is_pdb_enabled else 10,
170+
shutdown_timeout=None if is_pdb_enabled else 10,
171+
):
172+
...

0 commit comments

Comments
 (0)