Refactor death log handling in UserCharacterWorker: Introduced a new function optional_linked_names to streamline the retrieval of linked names (spouses, children, lovers) in the death context. This change enhances error handling and maintains the integrity of the deceased character's data in JSON format. Updated the handle_character_death method to utilize the new function, improving code readability and maintainability.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 2m55s

This commit is contained in:
Torsten Schulz (local)
2026-03-31 15:14:01 +02:00
parent b3578c65b8
commit 619e5e5123
2 changed files with 68 additions and 23 deletions

View File

@@ -31,6 +31,28 @@ fn collect_display_names(rows: Vec<Row>, key: &str) -> Vec<String> {
out
}
/// Verknüpfte Namen (Ehe, Kinder, Geliebte): optional — bei Schema-/SQL-Fehlern leere Liste,
/// damit der **Kern** (`deceased`) trotzdem als JSON in `notification.tr` landet.
fn optional_linked_names(
conn: &mut DbConnection,
log_label: &'static str,
stmt: &'static str,
query: &str,
deceased_character_id: i32,
) -> Vec<String> {
if let Err(e) = conn.prepare(stmt, query) {
eprintln!("[death_log] {log_label} prepare: {e}");
return Vec::new();
}
match conn.execute(stmt, &[&deceased_character_id]) {
Ok(rows) => collect_display_names(rows, "display_name"),
Err(e) => {
eprintln!("[death_log] {log_label} execute: {e}");
Vec::new()
}
}
}
/// Lädt Verstorbenen + Ehepartner, Kinder, **aktive Geliebte** (`tr = 'lover'`, `active IS NOT FALSE`).
/// Muss ausgeführt werden, bevor Beziehungen aus der DB gelöscht werden.
pub fn build_deceased_context(conn: &mut DbConnection, deceased_character_id: i32) -> Result<Value, DbError> {
@@ -62,21 +84,34 @@ pub fn build_deceased_context(conn: &mut DbConnection, deceased_character_id: i3
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(0);
conn.prepare("death_spouse", QUERY_DEATH_LOG_SPOUSE_DISPLAY_NAMES)?;
let spouse_rows = conn.execute("death_spouse", &[&deceased_character_id])?;
let spouses = collect_display_names(spouse_rows, "display_name");
conn.prepare("death_child", QUERY_DEATH_LOG_CHILD_DISPLAY_NAMES)?;
let child_rows = conn.execute("death_child", &[&deceased_character_id])?;
let children = collect_display_names(child_rows, "display_name");
conn.prepare("death_child_lover_birth", QUERY_DEATH_LOG_CHILD_LOVER_BIRTH_DISPLAY_NAMES)?;
let child_lover_rows = conn.execute("death_child_lover_birth", &[&deceased_character_id])?;
let lover_birth_children = collect_display_names(child_lover_rows, "display_name");
conn.prepare("death_lover", QUERY_DEATH_LOG_LOVER_DISPLAY_NAMES)?;
let lover_rows = conn.execute("death_lover", &[&deceased_character_id])?;
let lovers = collect_display_names(lover_rows, "display_name");
let spouses = optional_linked_names(
conn,
"spouse",
"death_spouse",
QUERY_DEATH_LOG_SPOUSE_DISPLAY_NAMES,
deceased_character_id,
);
let children = optional_linked_names(
conn,
"child",
"death_child",
QUERY_DEATH_LOG_CHILD_DISPLAY_NAMES,
deceased_character_id,
);
let lover_birth_children = optional_linked_names(
conn,
"child_lover_birth",
"death_child_lover_birth",
QUERY_DEATH_LOG_CHILD_LOVER_BIRTH_DISPLAY_NAMES,
deceased_character_id,
);
let lovers = optional_linked_names(
conn,
"lover",
"death_lover",
QUERY_DEATH_LOG_LOVER_DISPLAY_NAMES,
deceased_character_id,
);
Ok(json!({
"deceased": {

View File

@@ -806,6 +806,24 @@ impl UserCharacterWorker {
// Todes- und Erb-Logik
fn handle_character_death(&mut self, character_id: i32) -> Result<(), DbError> {
// Todes-Kontext **vor** Erbfolge und vor allen DELETEs (wie EventsWorker / CharacterCreationWorker).
// So ist der Charakter garantiert noch in `character`, und bei Race mit anderem Worker schlägt
// spätestens hier fehl — nicht erst nach `set_heir`.
let death_ctx = {
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
match death_log::build_deceased_context(&mut conn, character_id) {
Ok(c) => Some(c),
Err(e) => {
eprintln!("[UserCharacterWorker] Todes-Log Kontext: {e}");
None
}
}
};
self.set_heir(character_id)?;
let death_event = format!(
@@ -830,14 +848,6 @@ impl UserCharacterWorker {
conn.prepare("delete_election_candidate", QUERY_DELETE_ELECTION_CANDIDATE)?;
conn.prepare("insert_notification", QUERY_INSERT_NOTIFICATION)?;
let death_ctx = match death_log::build_deceased_context(&mut conn, character_id) {
Ok(c) => Some(c),
Err(e) => {
eprintln!("[UserCharacterWorker] Todes-Log Kontext: {e}");
None
}
};
let dir_result = conn.execute("delete_director", &[&character_id])?;
for row in dir_result {
if let Some(user_id) = row