fmt
Some checks failed
CI / Check / Test (push) Failing after 6m39s

This commit is contained in:
2026-06-02 23:50:20 +02:00
parent 9e13f04e9c
commit bf0350c87a
12 changed files with 97 additions and 132 deletions

View File

@@ -380,9 +380,7 @@ impl TryFrom<EventPayload> for DomainEvent {
end_date,
} => {
let wid = parse_uuid(&wrapup_id, "wrapup_id")?;
let uid = user_id
.map(|s| parse_uuid(&s, "user_id"))
.transpose()?;
let uid = user_id.map(|s| parse_uuid(&s, "user_id")).transpose()?;
let sd = chrono::NaiveDate::parse_from_str(&start_date, "%Y-%m-%d")
.map_err(|e| DomainError::ValidationError(e.to_string()))?;
let ed = chrono::NaiveDate::parse_from_str(&end_date, "%Y-%m-%d")

View File

@@ -88,15 +88,13 @@ impl WrapUpRepository for PostgresWrapUpRepository {
let id_str = id.value().to_string();
let status_str = status_to_str(status);
sqlx::query(
"UPDATE wrap_up_records SET status = $1, error_message = $2 WHERE id = $3",
)
.bind(status_str)
.bind(error)
.bind(&id_str)
.execute(&self.pool)
.await
.map_err(map_err)?;
sqlx::query("UPDATE wrap_up_records SET status = $1, error_message = $2 WHERE id = $3")
.bind(status_str)
.bind(error)
.bind(&id_str)
.execute(&self.pool)
.await
.map_err(map_err)?;
Ok(())
}
@@ -205,10 +203,7 @@ fn row_to_record(row: &sqlx::postgres::PgRow) -> Result<WrapUpRecord, DomainErro
let created_at_str: String = row.try_get("created_at").map_err(map_err)?;
let completed_at_str: Option<String> = row.try_get("completed_at").map_err(map_err)?;
let user_id = user_id_str
.as_deref()
.map(parse_uuid)
.transpose()?;
let user_id = user_id_str.as_deref().map(parse_uuid).transpose()?;
Ok(WrapUpRecord {
id: WrapUpId::from_uuid(parse_uuid(&id_str)?),
@@ -219,7 +214,10 @@ fn row_to_record(row: &sqlx::postgres::PgRow) -> Result<WrapUpRecord, DomainErro
report_json,
error_message,
created_at: parse_datetime(&created_at_str)?,
completed_at: completed_at_str.as_deref().map(parse_datetime).transpose()?,
completed_at: completed_at_str
.as_deref()
.map(parse_datetime)
.transpose()?,
})
}
@@ -261,9 +259,7 @@ impl WrapUpStatsQuery for PostgresWrapUpStatsQuery {
ORDER BY r.watched_at ASC"
);
let mut q = sqlx::query(&sql)
.bind(range.start)
.bind(range.end);
let mut q = sqlx::query(&sql).bind(range.start).bind(range.end);
if let Some(ref uid) = scope_bind {
q = q.bind(uid);
}
@@ -307,18 +303,9 @@ impl WrapUpStatsQuery for PostgresWrapUpStatsQuery {
let original_language: Option<String> =
row.try_get("original_language").map_err(map_err)?;
let genres = genres_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let keywords = keywords_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let cast = cast_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let genres = genres_map.get(&movie_id_str).cloned().unwrap_or_default();
let keywords = keywords_map.get(&movie_id_str).cloned().unwrap_or_default();
let cast = cast_map.get(&movie_id_str).cloned().unwrap_or_default();
let cast_names: Vec<(String, u32)> = cast
.iter()

View File

@@ -213,10 +213,7 @@ fn row_to_record(row: &sqlx::sqlite::SqliteRow) -> Result<WrapUpRecord, DomainEr
let created_at_str: String = row.try_get("created_at").map_err(map_err)?;
let completed_at_str: Option<String> = row.try_get("completed_at").map_err(map_err)?;
let user_id = user_id_str
.as_deref()
.map(parse_uuid)
.transpose()?;
let user_id = user_id_str.as_deref().map(parse_uuid).transpose()?;
Ok(WrapUpRecord {
id: WrapUpId::from_uuid(parse_uuid(&id_str)?),
@@ -227,7 +224,10 @@ fn row_to_record(row: &sqlx::sqlite::SqliteRow) -> Result<WrapUpRecord, DomainEr
report_json,
error_message,
created_at: parse_datetime(&created_at_str)?,
completed_at: completed_at_str.as_deref().map(parse_datetime).transpose()?,
completed_at: completed_at_str
.as_deref()
.map(parse_datetime)
.transpose()?,
})
}
@@ -270,9 +270,7 @@ impl WrapUpStatsQuery for SqliteWrapUpStatsQuery {
ORDER BY r.watched_at ASC"
);
let mut q = sqlx::query(&sql)
.bind(&start_str)
.bind(&end_str);
let mut q = sqlx::query(&sql).bind(&start_str).bind(&end_str);
if let Some(ref uid) = scope_bind {
q = q.bind(uid);
}
@@ -316,18 +314,9 @@ impl WrapUpStatsQuery for SqliteWrapUpStatsQuery {
let original_language: Option<String> =
row.try_get("original_language").map_err(map_err)?;
let genres = genres_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let keywords = keywords_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let cast = cast_map
.get(&movie_id_str)
.cloned()
.unwrap_or_default();
let genres = genres_map.get(&movie_id_str).cloned().unwrap_or_default();
let keywords = keywords_map.get(&movie_id_str).cloned().unwrap_or_default();
let cast = cast_map.get(&movie_id_str).cloned().unwrap_or_default();
let cast_names: Vec<(String, u32)> = cast
.iter()

View File

@@ -6,8 +6,8 @@ use domain::ports::{
MovieRepository, PasswordHasher, PersonCommand, PersonQuery, PosterFetcherClient,
RemoteWatchlistRepository, ReviewRepository, SearchCommand, SearchPort, SocialQueryPort,
StatsRepository, UserProfileFieldsRepository, UserRepository, WatchEventRepository,
WatchlistRepository, WrapUpRepository, WrapUpStatsQuery, WrapUpVideoRenderer,
WebhookTokenRepository,
WatchlistRepository, WebhookTokenRepository, WrapUpRepository, WrapUpStatsQuery,
WrapUpVideoRenderer,
};
use crate::config::AppConfig;

View File

@@ -1,6 +1,9 @@
use std::sync::Arc;
use domain::testing::{InMemoryWrapUpRepository, InMemoryWrapUpStatsQuery, NoopRemoteWatchlistRepository, NoopSocialQueryPort};
use domain::testing::{
InMemoryWrapUpRepository, InMemoryWrapUpStatsQuery, NoopRemoteWatchlistRepository,
NoopSocialQueryPort,
};
use domain::{
ports::{
AuthService, DiaryExporter, DiaryRepository, DocumentParser, EventPublisher, ImageStorage,

View File

@@ -205,26 +205,14 @@ fn compute_rating_extremes(rows: &[WrapUpMovieRow]) -> (Option<MovieRef>, Option
}
fn compute_chronological_extremes(rows: &[WrapUpMovieRow]) -> (Option<MovieRef>, Option<MovieRef>) {
let first = rows
.iter()
.min_by_key(|r| r.watched_at)
.map(movie_ref);
let last = rows
.iter()
.max_by_key(|r| r.watched_at)
.map(movie_ref);
let first = rows.iter().min_by_key(|r| r.watched_at).map(movie_ref);
let last = rows.iter().max_by_key(|r| r.watched_at).map(movie_ref);
(first, last)
}
fn compute_year_extremes(rows: &[WrapUpMovieRow]) -> (Option<MovieRef>, Option<MovieRef>) {
let oldest = rows
.iter()
.min_by_key(|r| r.release_year)
.map(movie_ref);
let newest = rows
.iter()
.max_by_key(|r| r.release_year)
.map(movie_ref);
let oldest = rows.iter().min_by_key(|r| r.release_year).map(movie_ref);
let newest = rows.iter().max_by_key(|r| r.release_year).map(movie_ref);
(oldest, newest)
}

View File

@@ -20,11 +20,11 @@ pub mod remote_watchlist;
pub use remote_watchlist::RemoteWatchlistEntry;
pub mod watch_event;
pub mod wrapup;
pub use wrapup::*;
pub use watch_event::{
ParsedPlaybackEvent, PersistedWatchEvent, WatchEvent, WatchEventSource, WatchEventStatus,
WebhookToken,
};
pub use wrapup::*;
pub use import::{
AnnotatedRow, DomainField, FieldMapping, FileFormat, ImportError, ImportRow, ParsedFile,

View File

@@ -1131,11 +1131,13 @@ impl WrapUpRepository for InMemoryWrapUpRepository {
.collect())
}
async fn list_global(
&self,
) -> Result<Vec<crate::models::wrapup::WrapUpRecord>, DomainError> {
async fn list_global(&self) -> Result<Vec<crate::models::wrapup::WrapUpRecord>, DomainError> {
let store = self.store.lock().unwrap();
Ok(store.iter().filter(|r| r.user_id.is_none()).cloned().collect())
Ok(store
.iter()
.filter(|r| r.user_id.is_none())
.cloned()
.collect())
}
async fn find_existing(
@@ -1184,9 +1186,7 @@ impl WrapUpRepository for PanicWrapUpRepository {
) -> Result<Vec<crate::models::wrapup::WrapUpRecord>, DomainError> {
panic!("PanicWrapUpRepository called")
}
async fn list_global(
&self,
) -> Result<Vec<crate::models::wrapup::WrapUpRecord>, DomainError> {
async fn list_global(&self) -> Result<Vec<crate::models::wrapup::WrapUpRecord>, DomainError> {
panic!("PanicWrapUpRepository called")
}
async fn find_existing(

View File

@@ -135,12 +135,9 @@ pub async fn get_report(
) -> impl IntoResponse {
match get_wrapup::execute(&state.app_ctx, WrapUpId::from_uuid(id)).await {
Ok(Some(record)) if record.status == WrapUpStatus::Ready => match record.report_json {
Some(json) => (
StatusCode::OK,
[("content-type", "application/json")],
json,
)
.into_response(),
Some(json) => {
(StatusCode::OK, [("content-type", "application/json")], json).into_response()
}
None => StatusCode::NOT_FOUND.into_response(),
},
Ok(Some(_)) => StatusCode::ACCEPTED.into_response(),
@@ -158,10 +155,7 @@ pub async fn get_report(
),
security(("bearer_auth" = []))
)]
pub async fn get_video(
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> impl IntoResponse {
pub async fn get_video(State(state): State<AppState>, Path(id): Path<Uuid>) -> impl IntoResponse {
let record = match state
.app_ctx
.repos
@@ -219,11 +213,21 @@ fn render_wrapup(
year: i32,
ctx: &application::ports::HtmlPageContext,
) -> axum::response::Response {
let rating_max = report.rating_distribution.iter().copied().max().unwrap_or(1).max(1);
let rating_pcts: [f64; 5] = std::array::from_fn(|i| {
report.rating_distribution[i] as f64 / rating_max as f64 * 100.0
});
let genre_max = report.top_genres.first().map(|g| g.count).unwrap_or(1).max(1);
let rating_max = report
.rating_distribution
.iter()
.copied()
.max()
.unwrap_or(1)
.max(1);
let rating_pcts: [f64; 5] =
std::array::from_fn(|i| report.rating_distribution[i] as f64 / rating_max as f64 * 100.0);
let genre_max = report
.top_genres
.first()
.map(|g| g.count)
.unwrap_or(1)
.max(1);
let genre_pcts: Vec<f64> = report
.top_genres
.iter()

View File

@@ -599,13 +599,23 @@ impl domain::ports::WrapUpRepository for Panic {
) -> Result<(), DomainError> {
panic!()
}
async fn set_complete(&self, _: &domain::value_objects::WrapUpId, _: &str) -> Result<(), DomainError> {
async fn set_complete(
&self,
_: &domain::value_objects::WrapUpId,
_: &str,
) -> Result<(), DomainError> {
panic!()
}
async fn get_by_id(&self, _: &domain::value_objects::WrapUpId) -> Result<Option<domain::models::wrapup::WrapUpRecord>, DomainError> {
async fn get_by_id(
&self,
_: &domain::value_objects::WrapUpId,
) -> Result<Option<domain::models::wrapup::WrapUpRecord>, DomainError> {
panic!()
}
async fn list_for_user(&self, _: uuid::Uuid) -> Result<Vec<domain::models::wrapup::WrapUpRecord>, DomainError> {
async fn list_for_user(
&self,
_: uuid::Uuid,
) -> Result<Vec<domain::models::wrapup::WrapUpRecord>, DomainError> {
panic!()
}
async fn list_global(&self) -> Result<Vec<domain::models::wrapup::WrapUpRecord>, DomainError> {

View File

@@ -196,10 +196,16 @@ async fn main() -> anyhow::Result<()> {
Arc::clone(&ctx.repos.movie),
Arc::clone(&ctx.repos.search_command),
)) as Arc<dyn EventHandler>;
let wrapup_handler = Arc::new(application::wrapup::event_handler::WrapUpEventHandler::new(
ctx.clone(),
)) as Arc<dyn EventHandler>;
let mut h = vec![poster, cleanup, search_cleanup, discovery_indexer, wrapup_handler];
let wrapup_handler = Arc::new(
application::wrapup::event_handler::WrapUpEventHandler::new(ctx.clone()),
) as Arc<dyn EventHandler>;
let mut h = vec![
poster,
cleanup,
search_cleanup,
discovery_indexer,
wrapup_handler,
];
if let Some(e) = enrichment_handler {
h.push(e);
}
@@ -240,9 +246,9 @@ async fn main() -> anyhow::Result<()> {
Arc::clone(&ctx.repos.search_command),
)) as Arc<dyn EventHandler>;
tracing::info!("federation event handler registered");
let wrapup_handler = Arc::new(application::wrapup::event_handler::WrapUpEventHandler::new(
ctx.clone(),
)) as Arc<dyn EventHandler>;
let wrapup_handler = Arc::new(
application::wrapup::event_handler::WrapUpEventHandler::new(ctx.clone()),
) as Arc<dyn EventHandler>;
let mut h = vec![
poster,
cleanup,