Add sleep management for productions in ProduceWorker: Implement logic to set productions to sleep when storage capacity is insufficient. Introduce methods for processing and retrieving sleep productions, enhancing inventory management and production flow control.

This commit is contained in:
Torsten Schulz (local)
2026-01-14 15:26:15 +01:00
parent f133f3999e
commit f32c4b1456
2 changed files with 182 additions and 3 deletions

View File

@@ -14,6 +14,8 @@ use crate::worker::sql::{
QUERY_DELETE_PRODUCTION,
QUERY_INSERT_INVENTORY,
QUERY_INSERT_UPDATE_PRODUCTION_LOG,
QUERY_SET_PRODUCTION_SLEEP,
QUERY_GET_SLEEP_PRODUCTIONS,
};
use crate::worker::insert_notification_conn;
@@ -44,6 +46,7 @@ pub struct ProduceWorker {
base: BaseWorker,
last_iteration: Option<Instant>,
last_start_fix: Option<Instant>,
last_sleep_check: Option<Instant>,
}
impl ProduceWorker {
@@ -52,6 +55,7 @@ impl ProduceWorker {
base: BaseWorker::new("ProduceWorker", pool, broker),
last_iteration: None,
last_start_fix: None,
last_sleep_check: None,
}
}
@@ -72,6 +76,8 @@ impl ProduceWorker {
self.base.set_current_step("Process Productions");
self.process_productions();
self.base.set_current_step("Process Sleep Productions");
self.process_sleep_productions();
self.base.set_current_step("Signal Activity");
// TODO: Später Analogie zu signalActivity() aus der C++-Basisklasse herstellen.
self.base.set_current_step("Loop Done");
@@ -215,12 +221,37 @@ impl ProduceWorker {
production_id,
} = *production;
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
self.delete_production(production_id);
self.add_production_to_log(region_id, user_id, product_id, quantity);
// Prüfe VOR dem Abschluss, ob genug Lagerplatz vorhanden ist
if self.has_enough_storage_capacity(branch_id, quantity) {
// Genug Platz: Produktion abschließen
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
self.delete_production(production_id);
self.add_production_to_log(region_id, user_id, product_id, quantity);
}
} else {
// Nicht genug Platz: Produktion auf sleep setzen
if let Err(err) = self.set_production_sleep(production_id) {
eprintln!("[ProduceWorker] Fehler beim Setzen von sleep für Produktion {}: {}", production_id, err);
}
}
}
fn has_enough_storage_capacity(&self, branch_id: i32, required_quantity: i32) -> bool {
let stocks = match self.get_available_stocks(branch_id) {
Ok(rows) => rows,
Err(err) => {
eprintln!("[ProduceWorker] Fehler in getAvailableStocks: {err}");
return false;
}
};
let total_free_capacity: i32 = stocks.iter()
.map(|stock| (stock.total_capacity - stock.filled).max(0))
.sum();
total_free_capacity >= required_quantity
}
fn add_to_inventory(
&mut self,
branch_id: i32,
@@ -458,6 +489,95 @@ impl ProduceWorker {
Ok(())
}
fn set_production_sleep(&self, production_id: i32) -> Result<(), crate::db::DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| crate::db::DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("set_production_sleep", QUERY_SET_PRODUCTION_SLEEP)?;
conn.execute("set_production_sleep", &[&production_id])?;
Ok(())
}
fn process_sleep_productions(&mut self) {
const SLEEP_CHECK_INTERVAL_SECS: u64 = 300; // 5 Minuten
let now = Instant::now();
let should_check = match self.last_sleep_check {
None => {
self.last_sleep_check = Some(now);
true
}
Some(last) => {
if now.saturating_duration_since(last).as_secs() >= SLEEP_CHECK_INTERVAL_SECS {
self.last_sleep_check = Some(now);
true
} else {
false
}
}
};
if !should_check {
return;
}
let sleep_productions = match self.get_sleep_productions() {
Ok(rows) => rows,
Err(err) => {
eprintln!("[ProduceWorker] Fehler beim Laden von sleep-Produktionen: {err}");
Vec::new()
}
};
for production in sleep_productions {
self.handle_sleep_production(&production);
}
}
fn get_sleep_productions(&self) -> Result<Vec<FinishedProduction>, crate::db::DbError> {
let rows = self.load_sleep_productions()?;
Ok(rows
.into_iter()
.filter_map(Self::map_row_to_finished_production)
.collect())
}
fn load_sleep_productions(&self) -> Result<Rows, crate::db::DbError> {
let mut conn = self
.base
.pool
.get()
.map_err(|e| crate::db::DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
conn.prepare("get_sleep_productions", QUERY_GET_SLEEP_PRODUCTIONS)?;
conn.execute("get_sleep_productions", &[])
}
fn handle_sleep_production(&mut self, production: &FinishedProduction) {
let FinishedProduction {
branch_id,
product_id,
quantity,
quality,
user_id,
region_id,
production_id,
} = *production;
// Prüfe erneut, ob jetzt genug Lagerplatz vorhanden ist
if self.has_enough_storage_capacity(branch_id, quantity) {
// Jetzt genug Platz: Produktion abschließen
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
self.delete_production(production_id);
self.add_production_to_log(region_id, user_id, product_id, quantity);
}
}
// Wenn immer noch nicht genug Platz: Produktion bleibt auf sleep
}
fn insert_or_update_production_log(
&self,
region_id: i32,