| """ |
| DI container — constructs every dependency ONCE at app startup and |
| wires services together. This is the composition root. |
| |
| No globals: the container is created in `create_app()` and stored on |
| `app.state.container`. Route handlers retrieve it via the `get_container` |
| FastAPI dependency. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from dataclasses import dataclass |
|
|
| from config.settings import Settings, DATA_DIR, GALLERY_DIR, UPLOADS_DIR, JOBS_DIR |
| from confidence.engine import ConfidenceEngine |
| from confidence.conflicts import ConflictDetector |
| from metrics.collector import MetricsCollector |
| from orchestrator.health import HealthMonitor |
| from orchestrator.runner import Orchestrator |
| from pipeline import ( |
| InputValidator, |
| ImagePreprocessor, |
| ImageHasher, |
| FeatureExtractor, |
| ) |
| from providers.registry import ProviderRegistry |
| from services.analysis_service import AnalysisService |
| from services.cache_service import CacheService |
| from services.detection_service import DetectionService |
| from services.export_service import ExportService |
| from services.face_index_service import FaceIndexService |
| from services.face_intelligence_service import FaceIntelligenceService |
| from services.forensic_metadata_service import ForensicMetadataService |
| from services.health_service import HealthService |
| from services.job_service import JobService |
| from services.location_intelligence_service import LocationIntelligenceService |
| from services.object_intelligence_service import ObjectIntelligenceService |
| from services.osint_service import OSINTService |
| from services.correlation_engine_service import CorrelationEngineService |
| from services.provider_service import ProviderService |
| from services.recognition_service import RecognitionService |
| from services.search_service import SearchService |
| from storage.artifacts import ArtifactStore |
| from storage.cache import Cache |
| from storage.database import Database |
| from storage.face_index import FaceIndex |
| from storage.reference_store import ReferenceStore |
|
|
|
|
| @dataclass |
| class ServiceContainer: |
| """Holds every wired service + infrastructure object.""" |
| settings: Settings |
| registry: ProviderRegistry |
| cache: Cache |
| database: Database |
| artifacts: ArtifactStore |
| reference_store: ReferenceStore |
| metrics: MetricsCollector |
| health_monitor: HealthMonitor |
| orchestrator: Orchestrator |
| confidence_engine: ConfidenceEngine |
| conflict_detector: ConflictDetector |
| validator: InputValidator |
| preprocessor: ImagePreprocessor |
| hasher: ImageHasher |
| feature_extractor: FeatureExtractor |
| detection_service: DetectionService |
| recognition_service: RecognitionService |
| search_service: SearchService |
| analysis_service: AnalysisService |
| job_service: JobService |
| osint_service: OSINTService |
| face_intelligence_service: FaceIntelligenceService |
| forensic_metadata_service: ForensicMetadataService |
| object_intelligence_service: ObjectIntelligenceService |
| location_intelligence_service: LocationIntelligenceService |
| correlation_engine_service: CorrelationEngineService |
| provider_service: ProviderService |
| cache_service: CacheService |
| health_service: HealthService |
| export_service: ExportService |
| face_index: FaceIndex |
| face_index_service: FaceIndexService |
|
|
|
|
| def build_container(settings: Settings | None = None) -> ServiceContainer: |
| """Construct the entire dependency graph. Called once at startup.""" |
| settings = settings or Settings() |
|
|
| |
| registry = ProviderRegistry(settings) |
| registry.discover() |
|
|
| cache = Cache( |
| ttl_seconds=settings.cache_ttl_seconds, |
| max_entries=settings.cache_max_entries, |
| ) |
| database = Database(path=settings.db_path) |
| artifacts = ArtifactStore(root=UPLOADS_DIR) |
| reference_store = ReferenceStore(root=GALLERY_DIR) |
|
|
| metrics = MetricsCollector( |
| failure_threshold=settings.circuit_breaker_failure_threshold, |
| recovery_seconds=settings.circuit_breaker_recovery_seconds, |
| ) |
| health_monitor = HealthMonitor(metrics=metrics.health) |
|
|
| orchestrator = Orchestrator( |
| registry=registry, |
| cache=cache, |
| metrics=metrics, |
| health=health_monitor, |
| settings=settings, |
| ) |
|
|
| confidence_engine = ConfidenceEngine() |
| conflict_detector = ConflictDetector() |
|
|
| |
| validator = InputValidator(max_bytes=settings.max_image_bytes) |
| preprocessor = ImagePreprocessor(max_dim=1024) |
| hasher = ImageHasher() |
| |
| from models.providers import ProviderCapability |
| detectors = registry.list_by_capability(ProviderCapability.DETECTION) |
| default_detector = detectors[0] if detectors else None |
| feature_extractor = FeatureExtractor(detector=default_detector) |
|
|
| |
| detection_service = DetectionService( |
| registry=registry, orchestrator=orchestrator, cache=cache, metrics=metrics, |
| validator=validator, preprocessor=preprocessor, hasher=hasher, |
| feature_extractor=feature_extractor, |
| confidence_engine=confidence_engine, conflict_detector=conflict_detector, |
| ) |
| recognition_service = RecognitionService( |
| orchestrator=orchestrator, metrics=metrics, |
| validator=validator, preprocessor=preprocessor, hasher=hasher, |
| feature_extractor=feature_extractor, reference_store=reference_store, |
| confidence_engine=confidence_engine, conflict_detector=conflict_detector, |
| ) |
| search_service = SearchService( |
| orchestrator=orchestrator, metrics=metrics, |
| validator=validator, preprocessor=preprocessor, hasher=hasher, |
| feature_extractor=feature_extractor, |
| confidence_engine=confidence_engine, conflict_detector=conflict_detector, |
| ) |
| analysis_service = AnalysisService( |
| orchestrator=orchestrator, metrics=metrics, |
| validator=validator, preprocessor=preprocessor, hasher=hasher, |
| feature_extractor=feature_extractor, |
| confidence_engine=confidence_engine, conflict_detector=conflict_detector, |
| ) |
| job_service = JobService( |
| detection=detection_service, |
| recognition=recognition_service, |
| search=search_service, |
| analysis=analysis_service, |
| database=database, |
| metrics=metrics, |
| job_timeout_seconds=settings.job_timeout_seconds, |
| ) |
| osint_service = OSINTService( |
| orchestrator=orchestrator, |
| metrics=metrics, |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| feature_extractor=feature_extractor, |
| ) |
| face_intelligence_service = FaceIntelligenceService( |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| feature_extractor=feature_extractor, |
| ) |
| forensic_metadata_service = ForensicMetadataService( |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| ) |
| object_intelligence_service = ObjectIntelligenceService( |
| orchestrator=orchestrator, |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| feature_extractor=feature_extractor, |
| ) |
| location_intelligence_service = LocationIntelligenceService( |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| ) |
| correlation_engine_service = CorrelationEngineService( |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| ) |
| provider_service = ProviderService(registry=registry) |
| cache_service = CacheService(cache=cache) |
| health_service = HealthService( |
| registry=registry, health_monitor=health_monitor, metrics=metrics, |
| version=settings.app_version, |
| ) |
| export_service = ExportService(database=database) |
|
|
| |
| face_index = FaceIndex(path=settings.face_index_path) |
| face_index_service = FaceIndexService( |
| settings=settings, |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| feature_extractor=feature_extractor, |
| face_index=face_index, |
| ) |
|
|
| return ServiceContainer( |
| settings=settings, |
| registry=registry, |
| cache=cache, |
| database=database, |
| artifacts=artifacts, |
| reference_store=reference_store, |
| metrics=metrics, |
| health_monitor=health_monitor, |
| orchestrator=orchestrator, |
| confidence_engine=confidence_engine, |
| conflict_detector=conflict_detector, |
| validator=validator, |
| preprocessor=preprocessor, |
| hasher=hasher, |
| feature_extractor=feature_extractor, |
| detection_service=detection_service, |
| recognition_service=recognition_service, |
| search_service=search_service, |
| analysis_service=analysis_service, |
| job_service=job_service, |
| osint_service=osint_service, |
| face_intelligence_service=face_intelligence_service, |
| forensic_metadata_service=forensic_metadata_service, |
| object_intelligence_service=object_intelligence_service, |
| location_intelligence_service=location_intelligence_service, |
| correlation_engine_service=correlation_engine_service, |
| provider_service=provider_service, |
| cache_service=cache_service, |
| health_service=health_service, |
| export_service=export_service, |
| face_index=face_index, |
| face_index_service=face_index_service, |
| ) |
|
|