# 事件驱动架构增强实施计划 > 设计规格: `docs/superpowers/specs/2026-04-26-event-driven-architecture-design.md` > 日期: 2026-04-26 | 状态: draft | 总周期: 2 周 --- ## Phase 1: 高优先级事件补发(Week 1) ### Task 1: dialysis_service 添加 dialysis_record.created/reviewed 事件 **涉及文件**: `crates/erp-health/src/service/dialysis_service.rs` **步骤**: `create_dialysis_record()` 成功后发布 `dialysis_record.created`(data: patient_id, dialysis_type, status, dialysis_date, duration, ultrafiltration_volume)。审核状态变更时发布 `dialysis_record.reviewed`(data: patient_id, reviewer_id, complication_notes)。payload 遵循统一信封(schema_version: "v1")。发布失败仅 warn 不阻断业务。 **验收**: 创建/审核后 domain_events 表出现对应事件;`cargo test` 通过。 ### Task 2: diagnosis_service 添加 diagnosis.created/updated 事件 **涉及文件**: `crates/erp-health/src/service/diagnosis_service.rs` **步骤**: `create_diagnosis()` 后发布 `diagnosis.created`(data: patient_id, icd_code, diagnosis_name, severity)。`update_diagnosis()` 后发布 `diagnosis.updated`,计算变更 diff(changed_fields[], old_values{}, new_values{})。 **验收**: diagnosis.updated 事件 data 含 changed_fields 差异;`cargo test` 通过。 ### Task 3: consent_service 添加 consent.granted/revoked 事件 **涉及文件**: `crates/erp-health/src/service/consent_service.rs` **步骤**: 签署时发布 `consent.granted`(data: patient_id, consent_type, consent_scope, granted_by, expires_at)。撤销时发布 `consent.revoked`(data: patient_id, consent_type, revoked_by, reason)。 **验收**: 签署/撤销后 domain_events 表出现事件;`cargo test` 通过。 --- ## Phase 2: 中低优先级事件 + Outbox 优化(Week 2) ### Task 4: points_service 添加 points.earned/exchanged 事件 **涉及文件**: `crates/erp-health/src/service/points_service.rs` **步骤**: earn 成功后发布 `points.earned`(data: patient_id, points, source_type, balance_after)。exchange 成功后发布 `points.exchanged`(data: patient_id, points, product_name, order_id, balance_after)。确保在事务提交后发布。 **验收**: 积分变动后 domain_events 出现事件;balance_after 正确反映余额。 ### Task 5: article_service 添加 article.published/rejected 事件 **涉及文件**: `crates/erp-health/src/service/article_service.rs` **步骤**: 审核通过发布 `article.published`(data: title, author_id, category_id, tags[])。审核驳回发布 `article.rejected`(data: title, reviewer_id, reason)。 **验收**: 审核操作后 domain_events 出现事件;`cargo test` 通过。 ### Task 6: daily_monitoring_service 添加 daily_monitoring.created 事件 **涉及文件**: `crates/erp-health/src/service/daily_monitoring_service.rs` **步骤**: 记录创建后发布 `daily_monitoring.created`(data: patient_id, monitoring_date, monitoring_type, values{})。 **验收**: 创建记录后 domain_events 出现事件;`cargo test` 通过。 ### Task 7: Outbox relay 从轮询改为 LISTEN/NOTIFY **涉及文件**: `crates/erp-server/src/outbox.rs`, `crates/erp-core/src/events.rs` **步骤**: `EventBus::publish()` 持久化后执行 `NOTIFY outbox_channel, ''`。outbox relay 用 `sqlx::PgListener` 监听 + `tokio::select!`(LISTEN 触发 + 30s 兜底轮询)。保留 `process_pending_events()` 不变,仅改变触发方式。PgListener 添加断线自动重连。 **验收**: 事件延迟 < 100ms;DB 轮询频率从 5s 降为 30s 兜底;`cargo test --workspace` 通过。 --- ## Phase 3: 事件 schema 版本化 + 清理(Week 2) ### Task 8: 事件 payload 添加 schema_version 字段 **涉及文件**: `crates/erp-core/src/events.rs`, `crates/erp-health/src/service/` 下所有发布事件的 service **步骤**: 在 erp-core 创建 `build_event_payload()` 辅助函数,自动填充 schema_version/timestamp/metadata。逐个 service(14 个模块)替换手动构建为调用辅助函数,统一信封格式。 **验收**: 所有事件 payload 含 schema_version 字段;`cargo test --workspace` 通过。 ### Task 9: Outbox 表分区或定期清理策略 **涉及文件**: `migration/src/m000075_domain_events_cleanup.rs`(新增), `erp-server/src/tasks/events_cleanup.rs`(新增) **步骤**: 迁移创建 `domain_events_archive` 表,添加 `cleanup_old_published_events()` SQL 函数(>90 天 published 事件迁移到归档表)。后台任务每日执行清理。归档表只读防篡改。 **验收**: 清理任务正确迁移 >90 天事件;`cargo test` 通过。 ### Task 10: 消费者幂等性(dedup key 检查) **涉及文件**: `migration/src/m000076_processed_events.rs`(新增), `crates/erp-core/src/events.rs` **步骤**: 迁移创建 `processed_events` 表(event_id + consumer_id 联合主键 + processed_at)。erp-core 添加 `is_processed()` / `mark_processed()` 辅助函数。消费者模式:收到事件 -> 查已处理 -> 跳过或执行 -> 插入记录。添加 7 天 TTL 清理任务。 **验收**: 重复消费同一事件时第二次被跳过;`cargo test --workspace` 通过。 --- ## 执行原则 1. **每 Task 完成后立即提交** — 不积压 2. **Phase 1 优先** — P0 事件(透析/诊断)是核心医疗流程 3. **事件发布不阻断业务** — publish 失败仅 warn,Outbox relay 兜底 4. **统一信封格式** — 使用 `build_event_payload` 保证一致性 5. **LISTEN/NOTIFY 保留兜底轮询** — 30s 轮询防 NOTIFY 丢失