refactor: split worker into bootstrap, event_loop, sweep modules

main.rs: 234 → 55 lines, just config + spawn + await.
bootstrap.rs: DI wiring, returns WorkerServices struct.
event_loop.rs: event dispatch with extracted helpers
  (enqueue_cmd, handle_job_completed, drain_one).
sweep.rs: fallback job drainer on interval.
This commit is contained in:
2026-05-31 23:09:21 +02:00
parent 7b5bb66b37
commit 6140ecd3ba
4 changed files with 234 additions and 185 deletions

View File

@@ -0,0 +1,74 @@
use std::sync::Arc;
use application::processing::{EnqueueJobHandler, ProcessNextJobHandler};
use domain::ports::JobRepository;
use crate::config::WorkerConfig;
use crate::factories::{
Repos, build_enqueue_handler, build_plugin_registry, build_process_next_handler,
};
pub struct WorkerServices {
pub process_next: Arc<ProcessNextJobHandler>,
pub enqueue: Arc<EnqueueJobHandler>,
pub job_repo: Arc<dyn JobRepository>,
pub event_consumer:
adapters_event_transport::EventConsumerAdapter<adapters_nats::NatsMessageSource>,
}
pub async fn build(config: &WorkerConfig) -> anyhow::Result<WorkerServices> {
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<dyn domain::ports::EventStore> =
Arc::new(adapters_postgres::PostgresEventStore::new(pool.clone()));
let repos = Repos::new(pool);
let file_storage = Arc::new(adapters_storage::LocalFileStorage::new(
&config.storage_path,
));
let sidecar_writer: Arc<dyn domain::ports::SidecarWriterPort> =
Arc::new(adapters_sidecar::XmpSidecarWriter);
let pub_transport = adapters_nats::NatsTransport::new(nats_client.clone());
let nats_publisher: Arc<dyn domain::ports::EventPublisher> = Arc::new(
adapters_event_transport::EventPublisherAdapter::new(pub_transport),
);
let event_pub: Arc<dyn domain::ports::EventPublisher> = Arc::new(
adapters_event_transport::CompositeEventPublisher::new(nats_publisher, event_store),
);
let extractor: Arc<dyn domain::ports::MetadataExtractorPort> =
Arc::new(adapters_exif::NomExifExtractor);
let thumbnail_gen: Arc<dyn domain::ports::ThumbnailGeneratorPort> =
Arc::new(adapters_thumbnail::ImageThumbnailGenerator);
let registry = Arc::new(build_plugin_registry(
&repos,
file_storage,
sidecar_writer,
extractor,
thumbnail_gen,
event_pub.clone(),
));
let process_next = Arc::new(build_process_next_handler(
&repos,
registry,
event_pub.clone(),
));
let job_repo: Arc<dyn JobRepository> = repos.job.clone();
let enqueue = Arc::new(build_enqueue_handler(&repos, event_pub));
let consumer_source = adapters_nats::NatsMessageSource::new(nats_client);
let event_consumer = adapters_event_transport::EventConsumerAdapter::new(consumer_source);
Ok(WorkerServices {
process_next,
enqueue,
job_repo,
event_consumer,
})
}