将单体 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 行,独立可维护。 编译零错误,测试全部通过。
101 lines
4.1 KiB
Rust
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
|
|
}
|