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 行,独立可维护。
编译零错误,测试全部通过。
This commit is contained in:
iven
2026-05-11 10:09:10 +08:00
parent 129a7b175c
commit 8c347a5de9
14 changed files with 1564 additions and 2871 deletions

View File

@@ -0,0 +1,124 @@
/// points.earned/exchanged/expired → 积分变动通知
pub fn spawn(state: &crate::state::HealthState) -> Vec<erp_core::events::SubscriptionHandle> {
let mut handles = Vec::new();
let (mut points_rx, points_handle) = state.event_bus.subscribe_filtered("points.".to_string());
handles.push(points_handle);
let points_db = state.db.clone();
let points_bus = state.event_bus.clone();
tokio::spawn(async move {
loop {
match points_rx.recv().await {
Some(event) if event.event_type == super::POINTS_EARNED => {
if erp_core::events::is_event_processed(
&points_db,
event.id,
"points_earned_notifier",
)
.await
.unwrap_or(false)
{
continue;
}
let patient_id = event.payload.get("patient_id").and_then(|v| v.as_str());
let amount = event.payload.get("amount").and_then(|v| v.as_u64());
if let (Some(pid), Some(amt)) = (patient_id, amount) {
let notify = erp_core::events::DomainEvent::new(
"message.send",
event.tenant_id,
erp_core::events::build_event_payload(serde_json::json!({
"channel": "in_app",
"recipient_type": "patient",
"recipient_id": pid,
"template_key": "POINTS_EARNED",
"params": { "amount": amt }
})),
);
points_bus.publish(notify, &points_db).await;
tracing::info!(patient_id = pid, amount = amt, "积分获得通知已发送");
}
let _ = erp_core::events::mark_event_processed(
&points_db,
event.id,
"points_earned_notifier",
)
.await;
}
Some(event) if event.event_type == super::POINTS_EXCHANGED => {
if erp_core::events::is_event_processed(
&points_db,
event.id,
"points_exchanged_notifier",
)
.await
.unwrap_or(false)
{
continue;
}
let patient_id = event.payload.get("patient_id").and_then(|v| v.as_str());
let amount = event.payload.get("amount").and_then(|v| v.as_u64());
if let (Some(pid), Some(amt)) = (patient_id, amount) {
let notify = erp_core::events::DomainEvent::new(
"message.send",
event.tenant_id,
erp_core::events::build_event_payload(serde_json::json!({
"channel": "in_app",
"recipient_type": "patient",
"recipient_id": pid,
"template_key": "POINTS_EXCHANGED",
"params": { "amount": amt }
})),
);
points_bus.publish(notify, &points_db).await;
tracing::info!(patient_id = pid, amount = amt, "积分兑换通知已发送");
}
let _ = erp_core::events::mark_event_processed(
&points_db,
event.id,
"points_exchanged_notifier",
)
.await;
}
Some(event) if event.event_type == super::POINTS_EXPIRED => {
if erp_core::events::is_event_processed(
&points_db,
event.id,
"points_expired_notifier",
)
.await
.unwrap_or(false)
{
continue;
}
let patient_id = event.payload.get("patient_id").and_then(|v| v.as_str());
let amount = event.payload.get("amount").and_then(|v| v.as_u64());
if let (Some(pid), Some(amt)) = (patient_id, amount) {
let notify = erp_core::events::DomainEvent::new(
"message.send",
event.tenant_id,
erp_core::events::build_event_payload(serde_json::json!({
"channel": "in_app",
"recipient_type": "patient",
"recipient_id": pid,
"template_key": "POINTS_EXPIRED",
"params": { "amount": amt }
})),
);
points_bus.publish(notify, &points_db).await;
tracing::info!(patient_id = pid, amount = amt, "积分过期通知已发送");
}
let _ = erp_core::events::mark_event_processed(
&points_db,
event.id,
"points_expired_notifier",
)
.await;
}
Some(_) => {}
None => break,
}
}
});
handles
}