diff --git a/src/worker/director.rs b/src/worker/director.rs index 550fb55..ebf1170 100644 --- a/src/worker/director.rs +++ b/src/worker/director.rs @@ -460,6 +460,7 @@ impl DirectorWorker { plan: &ProductionPlan, ) -> Result<(), DbError> { let running = plan.running_productions; + // Maximal zwei parallele Produktionen pro Branch zulassen. if running >= 2 { eprintln!( "[DirectorWorker] Bereits zu viele laufende Produktionen ({}), keine neue Produktion.", @@ -530,16 +531,23 @@ impl DirectorWorker { conn.prepare("insert_production", QUERY_INSERT_PRODUCTION)?; - let mut remaining = to_produce; + // Anzahl neuer Produktions-Jobs so begrenzen, dass zusammen mit den + // bereits laufenden maximal 2 parallele Produktionen pro Branch aktiv + // sind. Jeder Job wird in Batches von max. 100 Stück aufgeteilt. + let mut remaining_qty = to_produce; let mut inserted_total = 0; - while remaining > 0 { - let batch = remaining.min(100); + let mut started_jobs = 0; + let max_new_jobs = (2 - running).max(0); + + while remaining_qty > 0 && started_jobs < max_new_jobs { + let batch = remaining_qty.min(100); conn.execute( "insert_production", &[&plan.branch_id, &plan.product_id, &batch], )?; - remaining -= batch; + remaining_qty -= batch; inserted_total += batch; + started_jobs += 1; } eprintln!( diff --git a/src/worker/produce.rs b/src/worker/produce.rs index dac4db1..204f494 100644 --- a/src/worker/produce.rs +++ b/src/worker/produce.rs @@ -29,33 +29,55 @@ struct StockInfo { } // SQL-Queries analog zur C++-Implementierung +// Wichtig: Pro `production.id` darf hier **genau eine Zeile** zurückkommen. +// Durch die Joins auf Director/Knowledge kann es sonst zu Mehrfachzeilen mit +// unterschiedlicher berechneter Qualität kommen. Deshalb wird die Qualität +// über MAX() aggregiert und nach `production_id` gruppiert. const QUERY_GET_FINISHED_PRODUCTIONS: &str = r#" - SELECT DISTINCT - p.id AS production_id, + SELECT + p.id AS production_id, p.branch_id, p.product_id, p.quantity, p.start_timestamp, pr.production_time, - k.character_id, - CASE - WHEN k2.id IS NOT NULL - THEN (k.knowledge * 2 + k2.knowledge) / 3 - ELSE k.knowledge - END AS quality, + -- Aggregierte Qualitätsbewertung pro Produktion + MAX( + CASE + WHEN k2.id IS NOT NULL + THEN (k.knowledge * 2 + k2.knowledge) / 3 + ELSE k.knowledge + END + ) AS quality, br.region_id, br.falukant_user_id AS user_id FROM falukant_data.production p - JOIN falukant_type.product pr ON p.product_id = pr.id - JOIN falukant_data.branch br ON p.branch_id = br.id - JOIN falukant_data.character c ON c.user_id = br.falukant_user_id - JOIN falukant_data.knowledge k ON p.product_id = k.product_id AND k.character_id = c.id - JOIN falukant_data.stock s ON s.branch_id = br.id - LEFT JOIN falukant_data.director d ON d.employer_user_id = c.user_id + JOIN falukant_type.product pr + ON p.product_id = pr.id + JOIN falukant_data.branch br + ON p.branch_id = br.id + JOIN falukant_data.character c + ON c.user_id = br.falukant_user_id + JOIN falukant_data.knowledge k + ON p.product_id = k.product_id + AND k.character_id = c.id + JOIN falukant_data.stock s + ON s.branch_id = br.id + LEFT JOIN falukant_data.director d + ON d.employer_user_id = c.user_id LEFT JOIN falukant_data.knowledge k2 - ON k2.character_id = d.director_character_id - AND k2.product_id = p.product_id + ON k2.character_id = d.director_character_id + AND k2.product_id = p.product_id WHERE p.start_timestamp + INTERVAL '1 minute' * pr.production_time <= NOW() + GROUP BY + p.id, + p.branch_id, + p.product_id, + p.quantity, + p.start_timestamp, + pr.production_time, + br.region_id, + br.falukant_user_id ORDER BY p.start_timestamp; "#;