from collections.abc import Iterator import sqlalchemy.pool 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.twilio.client import TwilioClient 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 jinja2sql import Jinja2SQL from owsclient import OwsClient from app.adapters.db import Database from app.config import Settings, settings class AppModule(Module): @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, ) @provider(scope="singleton") def jinja2sql(self, settings: Settings) -> Jinja2SQL: return Jinja2SQL(searchpath=settings.jinja2sql_template_searchpath) @provider(scope="singleton") def db(self, settings: Settings, jinja2sql: Jinja2SQL) -> Iterator[Database]: with Database( url=settings.snowflake_url, engine_args={ "echo": settings.snowflake_echo, "poolclass": sqlalchemy.pool.QueuePool, "pool_size": settings.snowflake_pool_size, "max_overflow": settings.snowflake_pool_max_overflow, "pool_recycle": settings.snowflake_pool_recycle, "pool_pre_ping": settings.snowflake_pool_pre_ping, "pool_reset_on_return": settings.snowflake_pool_reset_on_return, "connect_args": settings.snowflake_connect_args, }, jinja2sql=jinja2sql, ) as db: yield db @provider(scope="singleton") def twilio_client(self, settings: Settings) -> Iterator[TwilioClient]: with TwilioClient( account_sid=settings.twilio_account_sid, auth_token=settings.twilio_auth_token, ) as client: yield client 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)