refactor(tests): reformat code and update dependency management
- Reorganized import statements in adapter tests for better readability - Replaced or_insert_with(Vec::new) with or_default() in test closures - Updated Cargo.lock with new dependency versions and checksums - Added TLS features to tonic dependency configuration - Included sqlx, chrono, and uuid dependencies with specific features - Added jsonwebtoken and arc-swap as project dependencies - Reformatted assertion statements to comply with line length limits - Adjusted base64 import order in engine codec module - Updated protobuf include statement formatting
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
//! Scheduled message dispatcher on `MessageService`.
|
||||
//!
|
||||
//! A background task that periodically scans for due scheduled messages
|
||||
//! and sends them through the normal message path.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::repo::CreateMessageInput;
|
||||
|
||||
use super::message::MessageService;
|
||||
|
||||
impl MessageService {
|
||||
/// Start the background scheduled-message dispatcher.
|
||||
/// Scans every 30 seconds for pending messages whose `scheduled_at` has passed.
|
||||
pub fn start_scheduled_dispatcher(self: std::sync::Arc<Self>) {
|
||||
tokio::spawn(async move {
|
||||
tracing::info!("Scheduled message dispatcher started (interval: 30s)");
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_secs(30)).await;
|
||||
|
||||
match self.process_due_scheduled().await {
|
||||
Ok(count) => {
|
||||
if count > 0 {
|
||||
tracing::info!(count, "Dispatched scheduled messages");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(error = %e, "Scheduled message dispatch failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Fetch and dispatch all due scheduled messages.
|
||||
async fn process_due_scheduled(&self) -> crate::ImksResult<usize> {
|
||||
let due = self.repo.get_due_scheduled().await?;
|
||||
let mut dispatched = 0;
|
||||
|
||||
for scheduled in due {
|
||||
let input = CreateMessageInput {
|
||||
channel_id: scheduled.channel_id,
|
||||
author_id: scheduled.author_id,
|
||||
thread_id: scheduled.thread_id,
|
||||
reply_to_message_id: scheduled.reply_to_message_id,
|
||||
message_type: "text".into(),
|
||||
body: scheduled.body.clone(),
|
||||
metadata: scheduled.metadata.clone(),
|
||||
system: false,
|
||||
};
|
||||
|
||||
match self.repo.create(&input).await {
|
||||
Ok(message) => {
|
||||
self.repo
|
||||
.mark_scheduled_sent(scheduled.id, message.id)
|
||||
.await?;
|
||||
|
||||
// Broadcast to channel
|
||||
if let Some(ns) = self.namespaces.get_namespace("/") {
|
||||
ns.emit_to_room(
|
||||
&scheduled.channel_id.to_string(),
|
||||
"message:new",
|
||||
serde_json::to_value(&message).unwrap_or_default(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
dispatched += 1;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(scheduled_id = %scheduled.id, error = %e, "Failed to send scheduled message");
|
||||
self.repo
|
||||
.mark_scheduled_failed(scheduled.id, &e.to_string())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(dispatched)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user