Skip to content

Commit

Permalink
Delay app initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
fajpunk committed Nov 8, 2024
1 parent c205f7a commit 126c1ca
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ USER appuser
EXPOSE 8080

# Run the application.
CMD ["uvicorn", "mobu.main:app", "--host", "0.0.0.0", "--port", "8080"]
CMD ["uvicorn", "mobu.main:create_app", "--host", "0.0.0.0", "--port", "8080"]
2 changes: 1 addition & 1 deletion docs/development/idfdev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ You can run mobu locally while having all of the actual business run against ser
# Don't set MOBU_GITHUB_CONFIG_PATH if you don't need any of the GitHub integrations.
export MOBU_GITHUB_CONFIG_PATH="$ci_config_path"
uvicorn mobu.main:app 2>&1
uvicorn mobu.main:create_app 2>&1
71 changes: 39 additions & 32 deletions src/mobu/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from .handlers.internal import internal_router
from .status import post_status

__all__ = ["app", "lifespan"]
__all__ = ["create_app", "lifespan"]


@asynccontextmanager
Expand Down Expand Up @@ -89,47 +89,54 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
if config.profile == Profile.production:
configure_uvicorn_logging(config.log_level)

app = FastAPI(
title="mobu",
description=metadata("mobu")["Summary"],
version=version("mobu"),
openapi_url=f"{config.path_prefix}/openapi.json",
docs_url=f"{config.path_prefix}/docs",
redoc_url=f"{config.path_prefix}/redoc",
lifespan=lifespan,
)
"""The main FastAPI application for mobu."""

# Attach the routers.
app.include_router(internal_router)
app.include_router(external_router, prefix=config.path_prefix)

if config.github_ci_app_config_path:
app.include_router(
github_ci_app_router, prefix=f"{config.path_prefix}/github/ci"
def create_app() -> FastAPI:
"""Create the main FastAPI application for mobu."""
app = FastAPI(
title="mobu",
description=metadata("mobu")["Summary"],
version=version("mobu"),
openapi_url=f"{config.path_prefix}/openapi.json",
docs_url=f"{config.path_prefix}/docs",
redoc_url=f"{config.path_prefix}/redoc",
lifespan=lifespan,
)

if config.github_refresh_app_config_path:
app.include_router(
github_refresh_app_router,
prefix=f"{config.path_prefix}/github/refresh",
)
# Attach the routers.
app.include_router(internal_router)
app.include_router(external_router, prefix=config.path_prefix)

if config.github_ci_app_config_path:
app.include_router(
github_ci_app_router, prefix=f"{config.path_prefix}/github/ci"
)

# Add middleware.
app.add_middleware(XForwardedMiddleware)
if config.github_refresh_app_config_path:
app.include_router(
github_refresh_app_router,
prefix=f"{config.path_prefix}/github/refresh",
)

# Add middleware.
app.add_middleware(XForwardedMiddleware)

# Enable Slack alerting for uncaught exceptions.
if config.alert_hook:
logger = structlog.get_logger("mobu")
SlackRouteErrorHandler.initialize(
str(config.alert_hook), "mobu", logger
)
logger.debug("Initialized Slack webhook")

# Enable Slack alerting for uncaught exceptions.
if config.alert_hook:
logger = structlog.get_logger("mobu")
SlackRouteErrorHandler.initialize(str(config.alert_hook), "mobu", logger)
logger.debug("Initialized Slack webhook")
# Enable the generic exception handler for client errors.
app.exception_handler(ClientRequestError)(client_request_error_handler)

# Enable the generic exception handler for client errors.
app.exception_handler(ClientRequestError)(client_request_error_handler)
return app


def create_openapi() -> str:
"""Create the OpenAPI spec for static documentation."""
app = create_app()
return json.dumps(
get_openapi(
title=app.title,
Expand Down
30 changes: 5 additions & 25 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from collections.abc import AsyncIterator, Iterator
from contextlib import asynccontextmanager
from importlib import reload
from pathlib import Path
from tempfile import TemporaryDirectory
from textwrap import dedent
Expand Down Expand Up @@ -101,11 +100,7 @@ def test_filesystem() -> Iterator[Path]:
def _enable_github_ci_app(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> Iterator[None]:
"""Enable the GitHub CI app functionality.
We need to reload the main module here because including the router is done
conditionally on module import.
"""
"""Enable the GitHub CI app functionality."""
github_config = tmp_path / "github_ci_app_config.yaml"
github_config.write_text(
dedent("""
Expand All @@ -132,22 +127,12 @@ def _enable_github_ci_app(
)
monkeypatch.setattr(config, "github_ci_app_config_path", github_config)

reload(main)

yield

reload(main)


@pytest.fixture
def _enable_github_refresh_app(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> Iterator[None]:
"""Enable the GitHub refresh app functionality.
We need to reload the main module here because including the router is done
conditionally on module import.
"""
"""Enable the GitHub refresh app functionality."""
github_config = tmp_path / "github_ci_app_refresh.yaml"
github_config.write_text(
dedent("""
Expand All @@ -166,12 +151,6 @@ def _enable_github_refresh_app(
config, "github_refresh_app_config_path", github_config
)

reload(main)

yield

reload(main)


@pytest_asyncio.fixture
async def app(jupyter: MockJupyter) -> AsyncIterator[FastAPI]:
Expand All @@ -189,8 +168,9 @@ async def app(jupyter: MockJupyter) -> AsyncIterator[FastAPI]:
A tests in :file:`business/jupyterloginloop_test.py` depends on the exact
shutdown timeout.
"""
async with LifespanManager(main.app, shutdown_timeout=10):
yield main.app
app = main.create_app()
async with LifespanManager(app, shutdown_timeout=10):
yield app


@pytest.fixture
Expand Down
3 changes: 2 additions & 1 deletion tests/support/monkeyflocker.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from rubin.nublado.client.testing import mock_jupyter
from starlette.middleware.base import BaseHTTPMiddleware

from mobu.main import app
from mobu.main import create_app as main_create_app

from .constants import TEST_BASE_URL
from .gafaelfawr import mock_gafaelfawr
Expand Down Expand Up @@ -45,5 +45,6 @@ def create_app() -> FastAPI:
respx.start()
mock_gafaelfawr(respx.mock)
mock_jupyter(respx.mock, base_url=TEST_BASE_URL, user_dir=Path())
app = main_create_app()
app.add_middleware(AddAuthHeaderMiddleware)
return app
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ commands = pre-commit run --all-files
[testenv:run]
description = Run the development server with auto-reload for code changes.
usedevelop = true
commands = uvicorn mobu.main:app --reload
commands = uvicorn mobu.main:create_app --reload

0 comments on commit 126c1ca

Please sign in to comment.