refactor: move person enrichment staleness check to application layer

This commit is contained in:
2026-06-11 14:01:44 +02:00
parent 338ecb71c8
commit 2074a2244e
3 changed files with 38 additions and 49 deletions

View File

@@ -1,32 +1,19 @@
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::Utc;
use domain::{ use domain::{
errors::DomainError, errors::DomainError,
events::DomainEvent, events::DomainEvent,
ports::{EventHandler, PersonCommand, PersonEnrichmentClient, PersonQuery}, ports::EventHandler,
}; };
const STALENESS_DAYS: i64 = 90; use application::context::AppContext;
pub struct PersonEnrichmentHandler { pub struct PersonEnrichmentHandler {
enrichment_client: Arc<dyn PersonEnrichmentClient>, ctx: AppContext,
person_query: Arc<dyn PersonQuery>,
person_command: Arc<dyn PersonCommand>,
} }
impl PersonEnrichmentHandler { impl PersonEnrichmentHandler {
pub fn new( pub fn new(ctx: AppContext) -> Self {
enrichment_client: Arc<dyn PersonEnrichmentClient>, Self { ctx }
person_query: Arc<dyn PersonQuery>,
person_command: Arc<dyn PersonCommand>,
) -> Self {
Self {
enrichment_client,
person_query,
person_command,
}
} }
} }
@@ -41,21 +28,6 @@ impl EventHandler for PersonEnrichmentHandler {
_ => return Ok(()), _ => return Ok(()),
}; };
if let Some(person) = self.person_query.get_by_id(&person_id).await? application::person::enrich::execute(&self.ctx, person_id, &external_person_id).await
&& let Some(at) = person.enriched_at()
&& (Utc::now() - at).num_days() < STALENESS_DAYS
{
tracing::debug!(person_id = %person_id.value(), "person enrichment still fresh");
return Ok(());
}
tracing::info!(person_id = %person_id.value(), "enriching person from TMDb");
let data = self
.enrichment_client
.fetch_details(&external_person_id)
.await?;
self.person_command
.update_enrichment(&person_id, &data)
.await
} }
} }

View File

@@ -1,16 +1,35 @@
use crate::context::AppContext; use crate::context::AppContext;
use chrono::Utc;
use domain::{ use domain::{
errors::DomainError, errors::DomainError,
models::{PersonEnrichmentData, PersonId}, models::PersonId,
}; };
pub async fn execute( const STALENESS_DAYS: i64 = 90;
ctx: &AppContext,
person_id: PersonId, pub async fn execute(ctx: &AppContext, person_id: PersonId, external_id: &str) -> Result<(), DomainError> {
data: PersonEnrichmentData, if let Some(person) = ctx.repos.person_query.get_by_id(&person_id).await?
) -> Result<(), DomainError> { && let Some(at) = person.enriched_at()
ctx.repos && (Utc::now() - at).num_days() < STALENESS_DAYS
.person_command {
.update_enrichment(&person_id, &data) tracing::debug!(person_id = %person_id.value(), "person enrichment still fresh");
.await return Ok(());
}
let client = ctx.services.person_enrichment.as_ref().ok_or_else(|| {
DomainError::InfrastructureError("person enrichment client not configured".into())
})?;
let data = match client.fetch_details(external_id).await {
Ok(d) => d,
Err(DomainError::NotFound(msg)) => {
tracing::warn!("TMDb person lookup found nothing: {msg}");
return Ok(());
}
Err(e) => return Err(e),
};
ctx.repos.person_command.update_enrichment(&person_id, &data).await?;
tracing::info!(person_id = %person_id.value(), "person enriched");
Ok(())
} }

View File

@@ -146,13 +146,11 @@ async fn main() -> anyhow::Result<()> {
Arc::clone(&ctx.repos.search_command), Arc::clone(&ctx.repos.search_command),
Arc::clone(&ctx.services.object_storage), Arc::clone(&ctx.services.object_storage),
)) as Arc<dyn EventHandler>; )) as Arc<dyn EventHandler>;
let person_handler = Arc::new(tmdb_enrichment::PersonEnrichmentHandler::new(
Arc::clone(&client) as Arc<dyn PersonEnrichmentClient>,
Arc::clone(&ctx.repos.person_query),
Arc::clone(&ctx.repos.person_command),
)) as Arc<dyn EventHandler>;
ctx.services.person_enrichment = ctx.services.person_enrichment =
Some(Arc::clone(&client) as Arc<dyn PersonEnrichmentClient>); Some(Arc::clone(&client) as Arc<dyn PersonEnrichmentClient>);
let person_handler = Arc::new(tmdb_enrichment::PersonEnrichmentHandler::new(
ctx.clone(),
)) as Arc<dyn EventHandler>;
let job = Arc::new(application::jobs::EnrichmentStalenessJob::new(ctx.clone())) let job = Arc::new(application::jobs::EnrichmentStalenessJob::new(ctx.clone()))
as Arc<dyn PeriodicJob>; as Arc<dyn PeriodicJob>;
(Some(handler), Some(person_handler), Some(job)) (Some(handler), Some(person_handler), Some(job))