"""Background worker that polls delivery providers for waybill updates.""" import asyncio import signal import httpx import structlog from app.adapters.delivery_providers.registry import ( resolve_delivery_provider_timeout_seconds, ) from app.adapters.delivery_providers.cdek.auth import CDEKAuthClient from app.adapters.delivery_providers.cdek.client import CDEKClient from app.adapters.delivery_providers.cse.client import CSEClient from app.adapters.delivery_providers.cse.order_mapper import ( CSEOrderRegistrationParams, ) from app.adapters.postgres.engine import ( create_postgres_engine, create_postgres_session_factory, ) from app.config import Settings, get_settings from app.repositories.order import OrderRepository from app.runtime.logging import configure_logging from app.services.waybill_poller import WaybillPollerService logger = structlog.get_logger(__name__) async def _run(settings: Settings, stop_event: asyncio.Event) -> None: http_client = httpx.AsyncClient( timeout=resolve_delivery_provider_timeout_seconds(settings.delivery_providers) ) order_info_adapters: dict[str, object] = {} waybill_info_adapters: dict[str, object] = {} cdek_config = settings.delivery_providers.cdek if cdek_config.enabled: auth_client = CDEKAuthClient( http_client=http_client, base_url=cdek_config.base_url, client_id=cdek_config.client_id, client_secret=cdek_config.client_secret, timeout_seconds=cdek_config.timeout_seconds, ) cdek_client = CDEKClient( http_client=http_client, auth_client=auth_client, base_url=cdek_config.base_url, timeout_seconds=cdek_config.timeout_seconds, retry_attempts=cdek_config.retry_attempts, retry_backoff_seconds=cdek_config.retry_backoff_seconds, ) order_info_adapters["cdek"] = cdek_client waybill_info_adapters["cdek"] = cdek_client cse_config = settings.delivery_providers.cse if cse_config.enabled: cse_client = CSEClient( http_client=http_client, base_url=cse_config.base_url, login=cse_config.login, password=cse_config.password, registration_params=CSEOrderRegistrationParams( payer=cse_config.payer, payment_method=cse_config.payment_method, shipping_method=cse_config.shipping_method, ), timeout_seconds=cse_config.timeout_seconds, retry_attempts=cse_config.retry_attempts, retry_backoff_seconds=cse_config.retry_backoff_seconds, ) order_info_adapters["cse"] = cse_client engine = create_postgres_engine(settings.postgres) session_factory = create_postgres_session_factory(engine) repository = OrderRepository(session_factory=session_factory) service = WaybillPollerService( order_repository=repository, order_info_adapters=order_info_adapters, waybill_info_adapters=waybill_info_adapters, batch_size=settings.waybill_poller.batch_size, ) logger.info( "waybill_poller_started", interval_seconds=settings.waybill_poller.interval_seconds, batch_size=settings.waybill_poller.batch_size, ) try: await service.run_forever( interval_seconds=settings.waybill_poller.interval_seconds, stop_event=stop_event, ) finally: await http_client.aclose() await engine.dispose() logger.info("waybill_poller_stopped") async def main() -> None: configure_logging() settings = get_settings() stop_event = asyncio.Event() loop = asyncio.get_running_loop() for sig in (signal.SIGTERM, signal.SIGINT): try: loop.add_signal_handler(sig, stop_event.set) except NotImplementedError: pass await _run(settings, stop_event) if __name__ == "__main__": asyncio.run(main())