refactor: move person enrichment staleness check to application layer
This commit is contained in:
@@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user