from collections.abc import Iterator import boto3 from anydi import Container, Module, Provider, provider from anydi.testing import TestContainer from fansifter_common import context from fansifter_common.adapters.aws.secretsmanager import SecretsManager from fansifter_common.adapters.db.base import Database from fansifter_common.constants import PROD_ENVIRONMENT, QA_ENVIRONMENT from fansifter_common.m2m_token import M2MTokenManager from fansifter_common.utils.functional import lazy_proxy from httpx import Timeout from mypy_boto3_kms import KMSClient from owsclient import OwsClient from app.adapters.db.twilio.repositories import TwilioAccountRepository from app.config import Settings, settings from app.validator import RequestValidator class AppModule(Module): @provider(scope="singleton") def kms_client(self, settings: Settings) -> KMSClient: return boto3.client("kms", region_name=settings.aws_region_name) # type: ignore @provider(scope="singleton") def pg_db( self, settings: Settings, ) -> Iterator[Database]: with Database( url=settings.postgres_url, engine_args=settings.postgres_engine_args, ) as db: yield db @provider(scope="singleton") def request_validator( self, db: Database, accounts_repository: TwilioAccountRepository, kms_client: KMSClient, settings: Settings, ) -> RequestValidator: return RequestValidator( db=db, accounts_repository=accounts_repository, kms_client=kms_client, kms_key_id=settings.kms_key_id, ) @provider(scope="singleton") def secrets_manager(self, settings: Settings) -> SecretsManager: return SecretsManager(region_name=settings.aws_region_name) @provider(scope="singleton") def m2m_token_manager( self, settings: Settings, secrets_manager: SecretsManager ) -> M2MTokenManager: return M2MTokenManager( secrets_manager=secrets_manager, secret_name_key=settings.m2m_token_secret_key_name, secret_expire_name_key=settings.m2m_token_secret_expiry_key_name, ) @provider(scope="singleton") def ows_client( self, settings: Settings, m2m_token_manager: M2MTokenManager ) -> OwsClient: return OwsClient( environment=settings.environment, service_name=settings.service_name, m2m_token_manager=m2m_token_manager if settings.environment in [QA_ENVIRONMENT, PROD_ENVIRONMENT] else None, correlation_id_getter=context.get_correlation_id, request_context_getter=context.get_request_context, timeout=Timeout(settings.ows_client_timeout), ) def initialize_container() -> Container: # Configure DI container container = Container( providers=[ Provider(lambda: settings, scope="singleton", interface=Settings), ], modules=[AppModule], ) if settings.environment == "test": return TestContainer.from_container(container) return container container = lazy_proxy(initialize_container)