Files
hms/crates/erp-health/src/event/health_data.rs
iven 8c347a5de9 refactor(health): 拆分 event.rs(2871 行)为 13 个领域文件
将单体 event.rs 按业务域拆分为 event/ 模块目录:
- mod.rs (219 行): 31 事件常量 + 调度器 + 测试
- 12 个消费者文件: workflow/device/alert/patient/appointment/
  follow_up/health_data/ai/consent/consultation/points/lab_report

每个消费者文件 50-215 行,独立可维护。
编译零错误,测试全部通过。
2026-05-11 10:09:10 +08:00

101 lines
4.1 KiB
Rust

/// health_data.critical_alert → 创建危急值告警记录
pub fn spawn(state: &crate::state::HealthState) -> Vec<erp_core::events::SubscriptionHandle> {
let mut handles = Vec::new();
let (mut critical_rx, critical_handle) = state
.event_bus
.subscribe_filtered("health_data.".to_string());
handles.push(critical_handle);
let critical_state = state.clone();
tokio::spawn(async move {
loop {
match critical_rx.recv().await {
Some(event) if event.event_type == super::HEALTH_DATA_CRITICAL_ALERT => {
// 幂等检查
if erp_core::events::is_event_processed(
&critical_state.db,
event.id,
"critical_alert_consumer",
)
.await
.unwrap_or(false)
{
continue;
}
let patient_id = event
.payload
.get("patient_id")
.and_then(|v| v.as_str())
.and_then(|s| uuid::Uuid::parse_str(s).ok());
// alert 数据在嵌套的 "alert" 对象中
let alert_obj = event.payload.get("alert");
let alert_type = "vital_sign";
let metric_name = alert_obj
.and_then(|a| a.get("indicator"))
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let metric_value = alert_obj
.and_then(|a| a.get("value"))
.and_then(|v| v.as_f64())
.map(|v| v.to_string())
.unwrap_or_default();
let threshold_value = alert_obj
.and_then(|a| a.get("threshold"))
.and_then(|v| v.as_f64())
.map(|v| v.to_string())
.unwrap_or_default();
let severity = alert_obj
.and_then(|a| a.get("level"))
.and_then(|v| v.as_str())
.unwrap_or("critical");
if let Some(pid) = patient_id {
match crate::service::critical_alert_service::handle_critical_alert_event(
&critical_state,
event.tenant_id,
pid,
alert_type,
metric_name,
&metric_value,
&threshold_value,
None,
severity,
)
.await
{
Ok(alert_id) => {
tracing::info!(
event_id = %event.id,
alert_id = %alert_id,
patient_id = %pid,
metric = %metric_name,
"危急值告警已创建"
);
let _ = erp_core::events::mark_event_processed(
&critical_state.db,
event.id,
"critical_alert_consumer",
)
.await;
}
Err(e) => {
tracing::error!(
event_id = %event.id,
patient_id = %pid,
error = %e,
"危急值告警创建失败"
);
}
}
}
}
Some(_) => {}
None => break,
}
}
});
handles
}