Enhance production job handling in DirectorWorker: Implemented a limit on the number of concurrent production jobs per branch to a maximum of two. Updated SQL query for fetching finished productions to aggregate quality ratings correctly and ensure unique results per production ID. Improved comments for clarity on the logic and SQL structure.

This commit is contained in:
Torsten Schulz (local)
2025-12-01 14:32:31 +01:00
parent 02bd0de75d
commit bd9fbb80c0
2 changed files with 50 additions and 20 deletions

View File

@@ -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!(

View File

@@ -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;
"#;