|
| 1 | +import logging |
1 | 2 | from collections.abc import AsyncGenerator |
2 | 3 | from contextlib import asynccontextmanager |
| 4 | +from logging import Logger |
3 | 5 |
|
| 6 | +from aspy_dependency_injection.service_collection import ServiceCollection |
| 7 | +from azure.cosmos import PartitionKey |
| 8 | +from azure.cosmos.aio import CosmosClient, DatabaseProxy |
| 9 | +from azure.identity import DefaultAzureCredential |
| 10 | +from azure.monitor.opentelemetry import ( |
| 11 | + configure_azure_monitor, # pyright: ignore[reportUnknownVariableType] |
| 12 | +) |
4 | 13 | from fastapi import FastAPI |
5 | 14 |
|
6 | | -from python_template.api.dependency_container import DependencyContainer |
| 15 | +from python_template.api.application_settings import ApplicationSettings |
| 16 | +from python_template.api.services.email_service import EmailService |
| 17 | +from python_template.api.workflows.products.discontinue_product.discontinue_product_workflow import ( |
| 18 | + DiscontinueProductWorkflow, |
| 19 | +) |
7 | 20 | from python_template.api.workflows.products.product_router import product_router |
| 21 | +from python_template.api.workflows.products.publish_product.publish_product_workflow import ( |
| 22 | + PublishProductWorkflow, |
| 23 | +) |
8 | 24 | from python_template.common.application_environment import ApplicationEnvironment |
| 25 | +from python_template.domain.entities.product import Product |
9 | 26 |
|
10 | 27 |
|
11 | | -@asynccontextmanager |
12 | | -async def lifespan(_: FastAPI) -> AsyncGenerator[None]: |
13 | | - await DependencyContainer.initialize() |
14 | | - yield |
15 | | - await DependencyContainer.uninitialize() |
| 28 | +def inject_application_settings() -> ApplicationSettings: |
| 29 | + return ApplicationSettings() # ty:ignore[missing-argument] |
16 | 30 |
|
17 | 31 |
|
18 | | -openapi_url = ( |
19 | | - "/openapi.json" |
20 | | - if ApplicationEnvironment.get_current() != ApplicationEnvironment.PRODUCTION |
21 | | - else None |
22 | | -) |
23 | | -app = FastAPI( |
24 | | - openapi_url=openapi_url, |
25 | | - lifespan=lifespan, |
26 | | -) |
27 | | -app.include_router(product_router) |
| 32 | +def inject_logging() -> Logger: |
| 33 | + return logging.getLogger(__name__) |
| 34 | + |
| 35 | + |
| 36 | +def inject_cosmos_client( |
| 37 | + application_settings: ApplicationSettings, |
| 38 | +) -> CosmosClient: |
| 39 | + return CosmosClient( |
| 40 | + url=application_settings.cosmos_db_no_sql_url, |
| 41 | + credential=application_settings.cosmos_db_no_sql_key.get_secret_value(), |
| 42 | + ) |
| 43 | + |
| 44 | + |
| 45 | +def inject_cosmos_database( |
| 46 | + application_settings: ApplicationSettings, cosmos_client: CosmosClient |
| 47 | +) -> DatabaseProxy: |
| 48 | + return cosmos_client.get_database_client( |
| 49 | + application_settings.cosmos_db_no_sql_database |
| 50 | + ) |
| 51 | + |
| 52 | + |
| 53 | +def configure_services() -> ServiceCollection: |
| 54 | + services = ServiceCollection() |
| 55 | + services.add_singleton(inject_application_settings) |
| 56 | + services.add_singleton(inject_logging) |
| 57 | + services.add_singleton(inject_cosmos_client) |
| 58 | + services.add_transient(inject_cosmos_database) |
| 59 | + services.add_transient(EmailService) |
| 60 | + services.add_transient(PublishProductWorkflow) |
| 61 | + services.add_transient(DiscontinueProductWorkflow) |
| 62 | + return services |
| 63 | + |
| 64 | + |
| 65 | +def create_app() -> FastAPI: |
| 66 | + @asynccontextmanager |
| 67 | + async def lifespan(_: FastAPI) -> AsyncGenerator[None]: |
| 68 | + async with configure_services().build_service_provider() as service_provider: |
| 69 | + application_settings = await service_provider.get_required_service( |
| 70 | + ApplicationSettings |
| 71 | + ) |
| 72 | + logging.basicConfig(level=application_settings.logging_level) |
| 73 | + |
| 74 | + if ApplicationEnvironment.get_current() != ApplicationEnvironment.LOCAL: |
| 75 | + configure_azure_monitor( |
| 76 | + connection_string=application_settings.application_insights_connection_string, |
| 77 | + credential=DefaultAzureCredential(), |
| 78 | + enable_live_metrics=True, |
| 79 | + ) |
| 80 | + |
| 81 | + if ApplicationEnvironment.get_current() == ApplicationEnvironment.LOCAL: |
| 82 | + cosmos_client = await service_provider.get_required_service( |
| 83 | + CosmosClient |
| 84 | + ) |
| 85 | + await cosmos_client.create_database_if_not_exists( |
| 86 | + application_settings.cosmos_db_no_sql_database |
| 87 | + ) |
| 88 | + cosmos_database = await service_provider.get_required_service( |
| 89 | + DatabaseProxy |
| 90 | + ) |
| 91 | + await cosmos_database.create_container_if_not_exists( |
| 92 | + id=Product.__name__, partition_key=PartitionKey("/id") |
| 93 | + ) |
| 94 | + yield |
| 95 | + |
| 96 | + openapi_url = ( |
| 97 | + "/openapi.json" |
| 98 | + if ApplicationEnvironment.get_current() != ApplicationEnvironment.PRODUCTION |
| 99 | + else None |
| 100 | + ) |
| 101 | + app = FastAPI(openapi_url=openapi_url, lifespan=lifespan) |
| 102 | + app.include_router(product_router) |
| 103 | + return app |
| 104 | + |
| 105 | + |
| 106 | +app = create_app() |
| 107 | +services = configure_services() |
| 108 | +services.configure_fastapi(app) |
0 commit comments