Clean up clippy warnings and improve code organization

- engine.rs: use is_none_or instead of map_or, remove redundant closures
- service/control.rs: move get_equipment_role_points before test module
- event.rs: replace complex 7-element tuple with PersistableEvent struct

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-04-21 19:49:27 +08:00
parent 706fb4f72a
commit 58fdb9f58e
3 changed files with 126 additions and 124 deletions

View File

@ -38,7 +38,7 @@ async fn supervise(state: AppState, store: Arc<ControlRuntimeStore>) {
match plc_platform_core::service::get_all_enabled_units(&state.platform.pool).await { match plc_platform_core::service::get_all_enabled_units(&state.platform.pool).await {
Ok(units) => { Ok(units) => {
for unit in units { for unit in units {
let needs_spawn = tasks.get(&unit.id).map_or(true, |h| h.is_finished()); let needs_spawn = tasks.get(&unit.id).is_none_or(|h| h.is_finished());
if needs_spawn { if needs_spawn {
let s = state.clone(); let s = state.clone();
let st = store.clone(); let st = store.clone();
@ -370,7 +370,7 @@ async fn check_fault_comm(
roles roles
.get("flt") .get("flt")
.and_then(|rp| monitor.get(&rp.point_id)) .and_then(|rp| monitor.get(&rp.point_id))
.map(|m| super::monitor_value_as_bool(m)) .map(super::monitor_value_as_bool)
.unwrap_or(false) .unwrap_or(false)
}); });
@ -381,7 +381,7 @@ async fn check_fault_comm(
roles roles
.get("flt") .get("flt")
.and_then(|rp| monitor.get(&rp.point_id)) .and_then(|rp| monitor.get(&rp.point_id))
.map(|m| super::monitor_value_as_bool(m)) .map(super::monitor_value_as_bool)
.unwrap_or(false) .unwrap_or(false)
}) })
.map(|(eq_id, _)| *eq_id) .map(|(eq_id, _)| *eq_id)

View File

@ -180,39 +180,41 @@ async fn fetch_equipment_code(pool: &sqlx::PgPool, id: Uuid) -> String {
.unwrap_or_else(|| id.to_string()) .unwrap_or_else(|| id.to_string())
} }
struct PersistableEvent {
event_type: &'static str,
level: &'static str,
unit_id: Option<Uuid>,
equipment_id: Option<Uuid>,
source_id: Option<Uuid>,
message: String,
payload: serde_json::Value,
}
async fn persist_event_if_needed( async fn persist_event_if_needed(
event: &AppEvent, event: &AppEvent,
pool: &sqlx::PgPool, pool: &sqlx::PgPool,
ws_manager: Option<&std::sync::Arc<WebSocketManager>>, ws_manager: Option<&std::sync::Arc<WebSocketManager>>,
) { ) {
let record: Option<( let record: Option<PersistableEvent> = match event {
&str,
&str,
Option<Uuid>,
Option<Uuid>,
Option<Uuid>,
String,
serde_json::Value,
)> = match event {
AppEvent::EquipmentStartCommandSent { AppEvent::EquipmentStartCommandSent {
equipment_id, equipment_id,
unit_id, unit_id,
point_id, point_id,
} => { } => {
let code = fetch_equipment_code(pool, *equipment_id).await; let code = fetch_equipment_code(pool, *equipment_id).await;
Some(( Some(PersistableEvent {
"feeder.equipment.start_command_sent", event_type: "feeder.equipment.start_command_sent",
"info", level: "info",
*unit_id, unit_id: *unit_id,
Some(*equipment_id), equipment_id: Some(*equipment_id),
None, source_id: None,
format!("Start command sent to equipment {}", code), message: format!("Start command sent to equipment {}", code),
serde_json::json!({ payload: serde_json::json!({
"equipment_id": equipment_id, "equipment_id": equipment_id,
"unit_id": unit_id, "unit_id": unit_id,
"point_id": point_id "point_id": point_id
}), }),
)) })
} }
AppEvent::EquipmentStopCommandSent { AppEvent::EquipmentStopCommandSent {
equipment_id, equipment_id,
@ -220,43 +222,43 @@ async fn persist_event_if_needed(
point_id, point_id,
} => { } => {
let code = fetch_equipment_code(pool, *equipment_id).await; let code = fetch_equipment_code(pool, *equipment_id).await;
Some(( Some(PersistableEvent {
"feeder.equipment.stop_command_sent", event_type: "feeder.equipment.stop_command_sent",
"info", level: "info",
*unit_id, unit_id: *unit_id,
Some(*equipment_id), equipment_id: Some(*equipment_id),
None, source_id: None,
format!("Stop command sent to equipment {}", code), message: format!("Stop command sent to equipment {}", code),
serde_json::json!({ payload: serde_json::json!({
"equipment_id": equipment_id, "equipment_id": equipment_id,
"unit_id": unit_id, "unit_id": unit_id,
"point_id": point_id "point_id": point_id
}), }),
)) })
} }
AppEvent::AutoControlStarted { unit_id } => { AppEvent::AutoControlStarted { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.auto_control_started", event_type: "feeder.unit.auto_control_started",
"info", level: "info",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!("Auto control started for unit {}", code), message: format!("Auto control started for unit {}", code),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::AutoControlStopped { unit_id } => { AppEvent::AutoControlStopped { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.auto_control_stopped", event_type: "feeder.unit.auto_control_stopped",
"info", level: "info",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!("Auto control stopped for unit {}", code), message: format!("Auto control stopped for unit {}", code),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::FaultLocked { AppEvent::FaultLocked {
unit_id, unit_id,
@ -264,54 +266,54 @@ async fn persist_event_if_needed(
} => { } => {
let unit_code = fetch_unit_code(pool, *unit_id).await; let unit_code = fetch_unit_code(pool, *unit_id).await;
let eq_code = fetch_equipment_code(pool, *equipment_id).await; let eq_code = fetch_equipment_code(pool, *equipment_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.fault_locked", event_type: "feeder.unit.fault_locked",
"error", level: "error",
Some(*unit_id), unit_id: Some(*unit_id),
Some(*equipment_id), equipment_id: Some(*equipment_id),
None, source_id: None,
format!( message: format!(
"Fault locked for unit {} by equipment {}", "Fault locked for unit {} by equipment {}",
unit_code, eq_code unit_code, eq_code
), ),
serde_json::json!({ "unit_id": unit_id, "equipment_id": equipment_id }), payload: serde_json::json!({ "unit_id": unit_id, "equipment_id": equipment_id }),
)) })
} }
AppEvent::FaultAcked { unit_id } => { AppEvent::FaultAcked { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.fault_acked", event_type: "feeder.unit.fault_acked",
"info", level: "info",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!("Fault acknowledged for unit {}", code), message: format!("Fault acknowledged for unit {}", code),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::CommLocked { unit_id } => { AppEvent::CommLocked { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.comm_locked", event_type: "feeder.unit.comm_locked",
"warn", level: "warn",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!("Communication locked for unit {}", code), message: format!("Communication locked for unit {}", code),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::CommRecovered { unit_id } => { AppEvent::CommRecovered { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.comm_recovered", event_type: "feeder.unit.comm_recovered",
"info", level: "info",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!("Communication recovered for unit {}", code), message: format!("Communication recovered for unit {}", code),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::RemLocal { AppEvent::RemLocal {
unit_id, unit_id,
@ -319,42 +321,42 @@ async fn persist_event_if_needed(
} => { } => {
let unit_code = fetch_unit_code(pool, *unit_id).await; let unit_code = fetch_unit_code(pool, *unit_id).await;
let eq_code = fetch_equipment_code(pool, *equipment_id).await; let eq_code = fetch_equipment_code(pool, *equipment_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.rem_local", event_type: "feeder.unit.rem_local",
"warn", level: "warn",
Some(*unit_id), unit_id: Some(*unit_id),
Some(*equipment_id), equipment_id: Some(*equipment_id),
None, source_id: None,
format!( message: format!(
"Unit {} switched to local control via equipment {}", "Unit {} switched to local control via equipment {}",
unit_code, eq_code unit_code, eq_code
), ),
serde_json::json!({ "unit_id": unit_id, "equipment_id": equipment_id }), payload: serde_json::json!({ "unit_id": unit_id, "equipment_id": equipment_id }),
)) })
} }
AppEvent::RemRecovered { unit_id } => { AppEvent::RemRecovered { unit_id } => {
let code = fetch_unit_code(pool, *unit_id).await; let code = fetch_unit_code(pool, *unit_id).await;
Some(( Some(PersistableEvent {
"feeder.unit.rem_recovered", event_type: "feeder.unit.rem_recovered",
"warn", level: "warn",
Some(*unit_id), unit_id: Some(*unit_id),
None, equipment_id: None,
None, source_id: None,
format!( message: format!(
"Unit {} returned to remote control; auto control requires manual restart", "Unit {} returned to remote control; auto control requires manual restart",
code code
), ),
serde_json::json!({ "unit_id": unit_id }), payload: serde_json::json!({ "unit_id": unit_id }),
)) })
} }
AppEvent::UnitStateChanged { .. } => None, AppEvent::UnitStateChanged { .. } => None,
}; };
let Some((event_type, level, unit_id, equipment_id, source_id, message, payload)) = record let Some(record) = record
else { else {
return; return;
}; };
let envelope = EventEnvelope::new(event_type, payload); let envelope = EventEnvelope::new(record.event_type, record.payload);
let inserted = sqlx::query_as::<_, EventRecord>( let inserted = sqlx::query_as::<_, EventRecord>(
r#" r#"
@ -364,11 +366,11 @@ async fn persist_event_if_needed(
"#, "#,
) )
.bind(envelope.event_type) .bind(envelope.event_type)
.bind(level) .bind(record.level)
.bind(unit_id as Option<Uuid>) .bind(record.unit_id)
.bind(equipment_id as Option<Uuid>) .bind(record.equipment_id)
.bind(source_id) .bind(record.source_id)
.bind(message) .bind(record.message)
.bind(sqlx::types::Json(envelope.payload)) .bind(sqlx::types::Json(envelope.payload))
.fetch_one(pool) .fetch_one(pool)
.await; .await;

View File

@ -431,21 +431,6 @@ pub async fn get_signal_role_points_batch(
.collect()) .collect())
} }
#[cfg(test)]
mod tests {
use super::{equipment_order_clause_with_unit, unit_order_clause};
#[test]
fn unit_ordering_defaults_to_code() {
assert_eq!(unit_order_clause(), "code");
}
#[test]
fn unit_equipment_ordering_uses_code_within_unit() {
assert_eq!(equipment_order_clause_with_unit(), "unit_id, code");
}
}
pub async fn get_equipment_role_points( pub async fn get_equipment_role_points(
pool: &PgPool, pool: &PgPool,
equipment_id: Uuid, equipment_id: Uuid,
@ -474,3 +459,18 @@ pub async fn get_equipment_role_points(
}) })
.collect()) .collect())
} }
#[cfg(test)]
mod tests {
use super::{equipment_order_clause_with_unit, unit_order_clause};
#[test]
fn unit_ordering_defaults_to_code() {
assert_eq!(unit_order_clause(), "code");
}
#[test]
fn unit_equipment_ordering_uses_code_within_unit() {
assert_eq!(equipment_order_clause_with_unit(), "unit_id, code");
}
}