use std::sync::Arc; use application::catalog::DeleteAssetHandler; use application::processing::{EnqueueJobHandler, ExecutePipelineHandler}; use domain::ports::{AssetRepository, JobRepository}; use crate::config::WorkerConfig; use crate::factories::{ Repos, build_enqueue_handler, build_executor, build_plugin_registry, }; pub struct WorkerServices { pub executor: Arc, pub enqueue: Arc, pub job_repo: Arc, pub asset_repo: Arc, pub delete_handler: Arc, pub trash_retention_days: u64, pub event_consumer: adapters_event_transport::EventConsumerAdapter, } pub async fn build(config: &WorkerConfig) -> anyhow::Result { let pool = adapters_postgres::connect(&config.database_url).await?; adapters_postgres::run_migrations(&pool).await?; let nats_client = async_nats::connect(&config.nats_url).await?; adapters_nats::ensure_stream(&nats_client).await?; tracing::info!(nats_url = %config.nats_url, "NATS connected"); let event_store: Arc = Arc::new(adapters_postgres::PostgresEventStore::new(pool.clone())); let repos = Repos::new(pool); let file_storage: Arc = Arc::new(adapters_storage::LocalFileStorage::new(&config.storage_path)); let sidecar_writer: Arc = Arc::new(adapters_sidecar::XmpSidecarWriter); let pub_transport = adapters_nats::NatsTransport::new(nats_client.clone()); let nats_publisher: Arc = Arc::new( adapters_event_transport::EventPublisherAdapter::new(pub_transport), ); let event_pub: Arc = Arc::new( adapters_event_transport::CompositeEventPublisher::new(nats_publisher, event_store), ); let extractor: Arc = Arc::new(adapters_exif::NomExifExtractor); let thumbnail_gen: Arc = Arc::new(adapters_thumbnail::ImageThumbnailGenerator); let registry = Arc::new(build_plugin_registry( &repos, file_storage.clone(), sidecar_writer, extractor, thumbnail_gen, event_pub.clone(), )); let executor = Arc::new(build_executor(&repos, registry, event_pub.clone())); let job_repo: Arc = repos.job.clone(); let asset_repo: Arc = repos.asset.clone(); let enqueue = Arc::new(build_enqueue_handler(&repos, event_pub.clone())); let sidecar_repo: Arc = repos.sidecar.clone(); let delete_handler = Arc::new(DeleteAssetHandler::new( repos.asset.clone(), repos.volume.clone(), repos.derivative.clone(), sidecar_repo, file_storage, event_pub, )); let consumer_source = adapters_nats::NatsMessageSource::new(nats_client); let event_consumer = adapters_event_transport::EventConsumerAdapter::new(consumer_source); Ok(WorkerServices { executor, enqueue, job_repo, asset_repo, delete_handler, trash_retention_days: config.trash_retention_days, event_consumer, }) }