refactor: remaining MEDIUM — CQRS splits, DI Deps, profile dedup, event Value, response enum

M1: MovieRepository→MovieCommand/MovieQuery, WatchEventRepository→
WatchEventCommand/WatchEventQuery
M2: goals/ and import/ use Deps structs
M7: extract upload_image helper in update_profile
M8: FederationDeliveryRequested activity_json String→serde_json::Value
M11: UserProfileResponse uses ProfileViewData enum
This commit is contained in:
2026-07-10 03:50:43 +02:00
parent 12da356a40
commit dee013c7eb
99 changed files with 1262 additions and 896 deletions

View File

@@ -7,11 +7,12 @@ use domain::{
AnnotatedRow, Movie,
import::{ImportRow, ParsedFile, RowResult},
},
ports::{DocumentParser, MovieRepository},
ports::{DocumentParser, MovieCommand},
testing::{InMemoryImportSessionRepository, InMemoryMovieRepository},
value_objects::{ExternalMetadataId, MovieTitle, ReleaseYear},
};
use crate::import::deps::{ApplyMappingDeps, CreateSessionDeps};
use crate::import::{
apply_mapping,
commands::{ApplyImportMappingCommand, CreateImportSessionCommand},
@@ -25,9 +26,13 @@ async fn applies_mapping_to_session() {
let b = TestContextBuilder::new();
let user_id = Uuid::new_v4();
let create_deps = CreateSessionDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: b.document_parser.clone(),
};
let session = create_session::execute(
Arc::clone(&sessions) as _,
b.document_parser.clone(),
&create_deps,
CreateImportSessionCommand {
user_id,
bytes: b"title\nTest".to_vec(),
@@ -37,10 +42,14 @@ async fn applies_mapping_to_session() {
.await
.unwrap();
let mapping_deps = ApplyMappingDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: b.document_parser.clone(),
movie_query: b.movie_query.clone(),
};
let rows = apply_mapping::execute(
Arc::clone(&sessions) as _,
b.document_parser.clone(),
b.movie_repo.clone(),
&mapping_deps,
ApplyImportMappingCommand {
user_id,
session_id: session.session_id.value(),
@@ -58,10 +67,14 @@ async fn fails_when_session_not_found() {
let sessions = InMemoryImportSessionRepository::new();
let b = TestContextBuilder::new();
let deps = ApplyMappingDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: b.document_parser.clone(),
movie_query: b.movie_query.clone(),
};
let result = apply_mapping::execute(
Arc::clone(&sessions) as _,
b.document_parser.clone(),
b.movie_repo.clone(),
&deps,
ApplyImportMappingCommand {
user_id: Uuid::new_v4(),
session_id: Uuid::new_v4(),
@@ -132,9 +145,13 @@ async fn marks_duplicate_by_external_id() {
let user_id = Uuid::new_v4();
let create_deps = CreateSessionDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: Arc::clone(&parser) as _,
};
let session = create_session::execute(
Arc::clone(&sessions) as _,
Arc::clone(&parser) as _,
&create_deps,
CreateImportSessionCommand {
user_id,
bytes: b"title\nKnown Movie".to_vec(),
@@ -144,10 +161,14 @@ async fn marks_duplicate_by_external_id() {
.await
.unwrap();
let mapping_deps = ApplyMappingDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: Arc::clone(&parser) as _,
movie_query: Arc::clone(&movies) as _,
};
let rows = apply_mapping::execute(
Arc::clone(&sessions) as _,
Arc::clone(&parser) as _,
Arc::clone(&movies) as _,
&mapping_deps,
ApplyImportMappingCommand {
user_id,
session_id: session.session_id.value(),
@@ -185,9 +206,13 @@ async fn marks_duplicate_by_title_and_year() {
let user_id = Uuid::new_v4();
let create_deps = CreateSessionDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: Arc::clone(&parser) as _,
};
let session = create_session::execute(
Arc::clone(&sessions) as _,
Arc::clone(&parser) as _,
&create_deps,
CreateImportSessionCommand {
user_id,
bytes: b"title\nDuplicate Film".to_vec(),
@@ -197,10 +222,14 @@ async fn marks_duplicate_by_title_and_year() {
.await
.unwrap();
let mapping_deps = ApplyMappingDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: Arc::clone(&parser) as _,
movie_query: Arc::clone(&movies) as _,
};
let rows = apply_mapping::execute(
Arc::clone(&sessions) as _,
Arc::clone(&parser) as _,
Arc::clone(&movies) as _,
&mapping_deps,
ApplyImportMappingCommand {
user_id,
session_id: session.session_id.value(),

View File

@@ -7,6 +7,7 @@ use domain::testing::{InMemoryImportProfileRepository, InMemoryImportSessionRepo
use domain::value_objects::{ImportProfileId, UserId};
use uuid::Uuid;
use crate::import::deps::ApplyProfileDeps;
use crate::import::{apply_profile, commands::ApplyImportProfileCommand};
#[tokio::test]
@@ -14,9 +15,13 @@ async fn fails_when_profile_not_found() {
let profiles = InMemoryImportProfileRepository::new();
let sessions = InMemoryImportSessionRepository::new();
let deps = ApplyProfileDeps {
import_profile: Arc::clone(&profiles) as _,
import_session: Arc::clone(&sessions) as _,
};
let result = apply_profile::execute(
Arc::clone(&profiles) as _,
Arc::clone(&sessions) as _,
&deps,
ApplyImportProfileCommand {
user_id: Uuid::new_v4(),
session_id: Uuid::new_v4(),
@@ -44,9 +49,13 @@ async fn fails_when_session_not_found() {
let profile_id = profile.id.clone();
profiles.save(&profile).await.unwrap();
let deps = ApplyProfileDeps {
import_profile: Arc::clone(&profiles) as _,
import_session: Arc::clone(&sessions) as _,
};
let result = apply_profile::execute(
Arc::clone(&profiles) as _,
Arc::clone(&sessions) as _,
&deps,
ApplyImportProfileCommand {
user_id,
session_id: Uuid::new_v4(),
@@ -82,9 +91,13 @@ async fn applies_profile_mappings_to_session() {
let session_id = session.id.clone();
sessions.create(&session).await.unwrap();
let deps = ApplyProfileDeps {
import_profile: Arc::clone(&profiles) as _,
import_session: Arc::clone(&sessions) as _,
};
apply_profile::execute(
Arc::clone(&profiles) as _,
Arc::clone(&sessions) as _,
&deps,
ApplyImportProfileCommand {
user_id,
session_id: session_id.value(),

View File

@@ -4,6 +4,7 @@ use uuid::Uuid;
use domain::testing::InMemoryImportSessionRepository;
use crate::import::deps::CreateSessionDeps;
use crate::import::{commands::CreateImportSessionCommand, create_session};
use crate::test_helpers::TestContextBuilder;
@@ -12,9 +13,13 @@ async fn creates_session_with_parsed_file() {
let sessions = InMemoryImportSessionRepository::new();
let b = TestContextBuilder::new();
let deps = CreateSessionDeps {
import_session: Arc::clone(&sessions) as _,
document_parser: b.document_parser.clone(),
};
let result = create_session::execute(
Arc::clone(&sessions) as _,
b.document_parser.clone(),
&deps,
CreateImportSessionCommand {
user_id: Uuid::new_v4(),
bytes: b"col1\nval1".to_vec(),

View File

@@ -7,6 +7,7 @@ use domain::value_objects::UserId;
use uuid::Uuid;
use crate::import::commands::ExecuteImportCommand;
use crate::import::deps::ExecuteImportDeps;
use crate::import::execute;
use crate::test_helpers::NoopReviewLogger;
@@ -50,9 +51,13 @@ async fn imports_confirmed_rows() {
let sid = session.id.clone();
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -76,9 +81,13 @@ async fn skips_unconfirmed_rows() {
let sid = session.id.clone();
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -96,9 +105,13 @@ async fn skips_unconfirmed_rows() {
async fn fails_when_session_not_found() {
let sessions = InMemoryImportSessionRepository::new();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: Uuid::new_v4(),
session_id: Uuid::new_v4(),
@@ -131,9 +144,13 @@ async fn handles_datetime_format() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -168,9 +185,13 @@ async fn fails_on_invalid_rating() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -205,9 +226,13 @@ async fn fails_on_missing_watched_at() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -242,9 +267,13 @@ async fn imports_row_with_external_metadata_id() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -279,9 +308,13 @@ async fn imports_row_with_director_and_comment() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -316,9 +349,13 @@ async fn handles_space_separated_datetime_format() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -348,9 +385,13 @@ async fn reports_invalid_row_result_errors() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -387,9 +428,13 @@ async fn fails_on_missing_rating() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -425,9 +470,13 @@ async fn fails_on_unparseable_date() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -463,9 +512,13 @@ async fn imports_row_without_release_year() {
}]);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -489,9 +542,13 @@ async fn deletes_session_after_import() {
sessions.create(&session).await.unwrap();
assert_eq!(sessions.count(), 1);
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),
@@ -533,10 +590,14 @@ async fn imports_more_rows_than_concurrency_limit() {
session.row_results = Some(rows);
sessions.create(&session).await.unwrap();
let deps = ExecuteImportDeps {
import_session: Arc::clone(&sessions) as _,
review_logger: Arc::new(NoopReviewLogger),
};
let confirmed_indices: Vec<usize> = (0..15).collect();
let result = execute::execute(
Arc::clone(&sessions) as _,
Arc::new(NoopReviewLogger),
&deps,
ExecuteImportCommand {
user_id: uid,
session_id: sid.value(),

View File

@@ -6,6 +6,7 @@ use domain::testing::{InMemoryImportProfileRepository, InMemoryImportSessionRepo
use domain::value_objects::UserId;
use uuid::Uuid;
use crate::import::deps::SaveProfileDeps;
use crate::import::{commands::SaveImportProfileCommand, save_profile};
#[tokio::test]
@@ -13,9 +14,13 @@ async fn fails_when_session_not_found() {
let sessions = InMemoryImportSessionRepository::new();
let profiles = InMemoryImportProfileRepository::new();
let deps = SaveProfileDeps {
import_session: Arc::clone(&sessions) as _,
import_profile: Arc::clone(&profiles) as _,
};
let result = save_profile::execute(
Arc::clone(&sessions) as _,
Arc::clone(&profiles) as _,
&deps,
SaveImportProfileCommand {
user_id: Uuid::new_v4(),
session_id: Uuid::new_v4(),
@@ -38,9 +43,13 @@ async fn saves_profile_from_session() {
session.field_mappings = Some(vec![]);
sessions.create(&session).await.unwrap();
let deps = SaveProfileDeps {
import_session: Arc::clone(&sessions) as _,
import_profile: Arc::clone(&profiles) as _,
};
let result = save_profile::execute(
Arc::clone(&sessions) as _,
Arc::clone(&profiles) as _,
&deps,
SaveImportProfileCommand {
user_id,
session_id: sid.value(),