Files
k-photos/crates/application/src/processing/commands/complete_job.rs

60 lines
1.7 KiB
Rust

use domain::{
entities::Job,
errors::DomainError,
events::DomainEvent,
ports::{EventPublisher, JobBatchRepository, JobRepository},
value_objects::{DateTimeStamp, StructuredData, SystemId},
};
use std::sync::Arc;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CompleteJobCommand {
pub job_id: SystemId,
pub result: StructuredData,
}
pub struct CompleteJobHandler {
job_repo: Arc<dyn JobRepository>,
batch_repo: Arc<dyn JobBatchRepository>,
event_pub: Arc<dyn EventPublisher>,
}
impl CompleteJobHandler {
pub fn new(
job_repo: Arc<dyn JobRepository>,
batch_repo: Arc<dyn JobBatchRepository>,
event_pub: Arc<dyn EventPublisher>,
) -> Self {
Self {
job_repo,
batch_repo,
event_pub,
}
}
pub async fn execute(&self, cmd: CompleteJobCommand) -> Result<Job, DomainError> {
let mut job = self
.job_repo
.find_by_id(&cmd.job_id)
.await?
.ok_or_else(|| DomainError::NotFound(format!("Job {} not found", cmd.job_id)))?;
job.complete(cmd.result);
self.job_repo.save(&job).await?;
if let Some(ref batch_id) = job.batch_id {
let mut batch =
self.batch_repo.find_by_id(batch_id).await?.ok_or_else(|| {
DomainError::NotFound(format!("Batch {} not found", batch_id))
})?;
batch.record_completion();
self.batch_repo.save(&batch).await?;
}
self.event_pub
.publish(DomainEvent::JobCompleted {
job_id: job.job_id,
timestamp: DateTimeStamp::now(),
})
.await?;
Ok(job)
}
}