refactor(person): EnrichPersonDeps + GetPersonDeps, PersonEnrichmentHandler
This commit is contained in:
14
crates/application/src/person/deps.rs
Normal file
14
crates/application/src/person/deps.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::ports::{EventPublisher, PersonCommand, PersonEnrichmentClient, PersonQuery};
|
||||
|
||||
pub struct GetPersonDeps {
|
||||
pub person_query: Arc<dyn PersonQuery>,
|
||||
pub event_publisher: Arc<dyn EventPublisher>,
|
||||
}
|
||||
|
||||
pub struct EnrichPersonDeps {
|
||||
pub person_query: Arc<dyn PersonQuery>,
|
||||
pub person_enrichment: Option<Arc<dyn PersonEnrichmentClient>>,
|
||||
pub person_command: Arc<dyn PersonCommand>,
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
use crate::context::AppContext;
|
||||
use chrono::Utc;
|
||||
use domain::{errors::DomainError, models::PersonId};
|
||||
|
||||
use super::deps::EnrichPersonDeps;
|
||||
|
||||
const STALENESS_DAYS: i64 = 90;
|
||||
|
||||
pub async fn execute(
|
||||
ctx: &AppContext,
|
||||
deps: &EnrichPersonDeps,
|
||||
person_id: PersonId,
|
||||
external_id: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
if let Some(person) = ctx.repos.person_query.get_by_id(&person_id).await?
|
||||
if let Some(person) = deps.person_query.get_by_id(&person_id).await?
|
||||
&& let Some(at) = person.enriched_at()
|
||||
&& (Utc::now() - at).num_days() < STALENESS_DAYS
|
||||
{
|
||||
@@ -17,7 +18,7 @@ pub async fn execute(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let client = ctx.services.person_enrichment.as_ref().ok_or_else(|| {
|
||||
let client = deps.person_enrichment.as_ref().ok_or_else(|| {
|
||||
DomainError::InfrastructureError("person enrichment client not configured".into())
|
||||
})?;
|
||||
|
||||
@@ -30,8 +31,7 @@ pub async fn execute(
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
ctx.repos
|
||||
.person_command
|
||||
deps.person_command
|
||||
.update_enrichment(&person_id, &data)
|
||||
.await?;
|
||||
tracing::info!(person_id = %person_id.value(), "person enriched");
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::context::AppContext;
|
||||
use chrono::Utc;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
@@ -6,15 +5,16 @@ use domain::{
|
||||
models::{Person, PersonId},
|
||||
};
|
||||
|
||||
use super::deps::GetPersonDeps;
|
||||
|
||||
const ENRICHMENT_TTL_DAYS: i64 = 90;
|
||||
|
||||
pub async fn execute(ctx: &AppContext, id: PersonId) -> Result<Option<Person>, DomainError> {
|
||||
let person = ctx.repos.person_query.get_by_id(&id).await?;
|
||||
pub async fn execute(deps: &GetPersonDeps, id: PersonId) -> Result<Option<Person>, DomainError> {
|
||||
let person = deps.person_query.get_by_id(&id).await?;
|
||||
if let Some(ref p) = person
|
||||
&& should_enrich(p)
|
||||
{
|
||||
let _ = ctx
|
||||
.services
|
||||
let _ = deps
|
||||
.event_publisher
|
||||
.publish(&DomainEvent::PersonEnrichmentRequested {
|
||||
person_id: id,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::context::AppContext;
|
||||
use chrono::Utc;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
@@ -6,13 +5,14 @@ use domain::{
|
||||
models::{Person, PersonCredits, PersonId},
|
||||
};
|
||||
|
||||
use super::deps::GetPersonDeps;
|
||||
|
||||
const ENRICHMENT_TTL_DAYS: i64 = 90;
|
||||
|
||||
pub async fn execute(ctx: &AppContext, id: PersonId) -> Result<PersonCredits, DomainError> {
|
||||
let credits = ctx.repos.person_query.get_credits(&id).await?;
|
||||
pub async fn execute(deps: &GetPersonDeps, id: PersonId) -> Result<PersonCredits, DomainError> {
|
||||
let credits = deps.person_query.get_credits(&id).await?;
|
||||
if should_enrich(&credits.person) {
|
||||
let _ = ctx
|
||||
.services
|
||||
let _ = deps
|
||||
.event_publisher
|
||||
.publish(&DomainEvent::PersonEnrichmentRequested {
|
||||
person_id: id,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod deps;
|
||||
pub mod enrich;
|
||||
pub mod get;
|
||||
pub mod get_credits;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
use domain::models::PersonId;
|
||||
use domain::testing::{FakePersonQuery, NoopEventPublisher};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::person::get;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
use crate::person::{deps::GetPersonDeps, get};
|
||||
|
||||
#[tokio::test]
|
||||
async fn returns_none_for_unknown_person() {
|
||||
let ctx = TestContextBuilder::new().build();
|
||||
let deps = GetPersonDeps {
|
||||
person_query: Arc::new(FakePersonQuery),
|
||||
event_publisher: NoopEventPublisher::new(),
|
||||
};
|
||||
|
||||
let result = get::execute(&ctx, PersonId::from_uuid(Uuid::new_v4()))
|
||||
let result = get::execute(&deps, PersonId::from_uuid(Uuid::new_v4()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
use domain::models::PersonId;
|
||||
use domain::testing::{FakePersonQuery, NoopEventPublisher};
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::person::get_credits;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
use crate::person::{deps::GetPersonDeps, get_credits};
|
||||
|
||||
#[tokio::test]
|
||||
async fn returns_empty_credits() {
|
||||
let ctx = TestContextBuilder::new().build();
|
||||
let deps = GetPersonDeps {
|
||||
person_query: Arc::new(FakePersonQuery),
|
||||
event_publisher: NoopEventPublisher::new(),
|
||||
};
|
||||
|
||||
let result = get_credits::execute(&ctx, PersonId::from_uuid(Uuid::new_v4()))
|
||||
let result = get_credits::execute(&deps, PersonId::from_uuid(Uuid::new_v4()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user