feat: search reindex, worker improvements, person IDs, user display names

- add admin POST /api/v1/admin/reindex-search endpoint + event-driven handler
- backfill persons from movie_cast/movie_crew into persons table
- paginate person list_page/backfill_from_credits_batch to cap memory
- concurrent worker event dispatch with semaphore (max 8)
- graceful worker shutdown (drain in-flight tasks on SIGINT)
- always ack events, log handler errors as warnings (no infinite retry)
- NATS ack_wait 600s, AtomicBool guard against concurrent reindex
- add username/display_name to UserSummaryDto and users list
- add person_id to CastMemberDto/CrewMemberDto via get_movie_profile use case
- add movie_id to wrapup MovieRef, person_id to wrapup PersonStat
- thread tmdb_person_id through wrapup cast pipeline
- add is_federated to FeedEntryDto
- cap orphaned persons query with LIMIT 500
- add SPA link to classic site footer
This commit is contained in:
2026-06-04 14:43:28 +02:00
parent af8e58aeb8
commit bd7dc648c4
36 changed files with 693 additions and 118 deletions

View File

@@ -461,6 +461,8 @@ impl FeedEntry {
pub struct UserSummary {
pub user_id: UserId,
email: Email,
username: Username,
display_name: Option<String>,
pub total_movies: i64,
pub avg_rating: Option<f64>,
pub avatar_path: Option<String>,
@@ -470,6 +472,8 @@ impl UserSummary {
pub fn new(
user_id: UserId,
email: Email,
username: Username,
display_name: Option<String>,
total_movies: i64,
avg_rating: Option<f64>,
avatar_path: Option<String>,
@@ -477,6 +481,8 @@ impl UserSummary {
Self {
user_id,
email,
username,
display_name,
total_movies,
avg_rating,
avatar_path,
@@ -485,6 +491,12 @@ impl UserSummary {
pub fn email(&self) -> &str {
self.email.value()
}
pub fn username(&self) -> &str {
self.username.value()
}
pub fn display_name(&self) -> Option<&str> {
self.display_name.as_deref()
}
}
#[derive(Clone, Debug)]

View File

@@ -36,6 +36,7 @@ impl DateRange {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MovieRef {
pub movie_id: Option<Uuid>,
pub title: String,
pub year: u16,
pub runtime_minutes: Option<u32>,
@@ -50,6 +51,7 @@ pub struct UserRef {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct PersonStat {
pub person_id: Option<Uuid>,
pub name: String,
pub count: u32,
pub avg_rating: f64,