feat(message): add cross-module event integration (Phase 6)

- Message module subscribes to workflow events (process_instance.started)
- Auto-generates notifications when workflows start
- Added started_by to workflow instance event payload
- Event listener runs as background tokio task

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-04-11 12:28:13 +08:00
parent 5ceed71e62
commit c0523e19b4
3 changed files with 88 additions and 4 deletions

View File

@@ -57,6 +57,43 @@ impl MessageModule {
put(subscription_handler::update_subscription),
)
}
/// 启动后台事件监听任务,将工作流事件转化为消息通知。
///
/// 在 main.rs 中调用,因为需要 db 连接。
pub fn start_event_listener(db: sea_orm::DatabaseConnection, event_bus: EventBus) {
use sea_orm::ConnectionTrait;
let mut rx = event_bus.subscribe();
tokio::spawn(async move {
loop {
match rx.recv().await {
Ok(event) => {
let db = db.clone();
let event_bus = event_bus.clone();
tokio::spawn(async move {
if let Err(e) =
handle_workflow_event(&event, &db, &event_bus).await
{
tracing::warn!(
event_type = %event.event_type,
error = %e,
"Failed to handle workflow event for messages"
);
}
});
}
Err(tokio::sync::broadcast::error::RecvError::Lagged(n)) => {
tracing::warn!(skipped = n, "Event listener lagged, skipping events");
}
Err(tokio::sync::broadcast::error::RecvError::Closed) => {
tracing::info!("Event bus closed, stopping message event listener");
break;
}
}
}
});
}
}
impl Default for MessageModule {
@@ -97,3 +134,46 @@ impl ErpModule for MessageModule {
self
}
}
/// 处理工作流事件,生成对应的消息通知。
async fn handle_workflow_event(
event: &erp_core::events::DomainEvent,
db: &sea_orm::DatabaseConnection,
event_bus: &EventBus,
) -> Result<(), String> {
match event.event_type.as_str() {
"process_instance.started" => {
let instance_id = event.payload.get("instance_id")
.and_then(|v| v.as_str())
.unwrap_or("unknown");
let starter_id = event.payload.get("started_by")
.and_then(|v| v.as_str());
if let Some(starter) = starter_id {
let recipient = match uuid::Uuid::parse_str(starter) {
Ok(id) => id,
Err(_) => return Ok(()),
};
let _ = crate::service::message_service::MessageService::send_system(
event.tenant_id,
recipient,
"流程已启动".to_string(),
format!("您的流程实例 {} 已启动执行。", instance_id),
"normal",
Some("workflow_instance".to_string()),
uuid::Uuid::parse_str(instance_id).ok(),
db,
event_bus,
)
.await
.map_err(|e| e.to_string())?;
}
}
"task.completed" => {
// 任务完成时通知发起人(此处简化处理)
tracing::debug!("Task completed event received, skipping notification for now");
}
_ => {}
}
Ok(())
}