Periodically verify the status of messages sent over mycelium
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
113
src/router.rs
113
src/router.rs
@@ -4,8 +4,8 @@ use serde_json::{Value, json};
|
||||
use tokio::sync::Semaphore;
|
||||
|
||||
use crate::{
|
||||
clients::{Destination, SupervisorClient},
|
||||
models::{Job, Message, MessageStatus, ScriptType},
|
||||
clients::{Destination, SupervisorClient, MyceliumClient},
|
||||
models::{Job, Message, MessageStatus, ScriptType, TransportStatus},
|
||||
service::AppService,
|
||||
};
|
||||
|
||||
@@ -15,7 +15,9 @@ pub struct RouterConfig {
|
||||
pub concurrency: usize,
|
||||
pub base_url: String, // e.g. http://127.0.0.1:8990
|
||||
pub topic: String, // e.g. "supervisor.rpc"
|
||||
// secret currently unused (None), add here later if needed
|
||||
// Transport status polling configuration
|
||||
pub transport_poll_interval_secs: u64, // e.g. 2
|
||||
pub transport_poll_timeout_secs: u64, // e.g. 300 (5 minutes)
|
||||
}
|
||||
|
||||
/// Start background router loops, one per context.
|
||||
@@ -130,13 +132,116 @@ async fn deliver_one(
|
||||
let params = build_params(&msg)?;
|
||||
|
||||
// Send
|
||||
let _out_id = client.call(&method, params).await?;
|
||||
let out_id = client.call(&method, params).await?;
|
||||
|
||||
// Store transport id and initial Sent status
|
||||
let _ = service
|
||||
.update_message_transport(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
Some(out_id.clone()),
|
||||
Some(TransportStatus::Sent),
|
||||
)
|
||||
.await;
|
||||
|
||||
// Mark as acknowledged on success
|
||||
service
|
||||
.update_message_status(context_id, caller_id, id, MessageStatus::Acknowledged)
|
||||
.await?;
|
||||
|
||||
// Spawn transport-status poller
|
||||
{
|
||||
let service_poll = service.clone();
|
||||
let base_url = cfg.base_url.clone();
|
||||
let poll_interval = std::time::Duration::from_secs(cfg.transport_poll_interval_secs);
|
||||
let poll_timeout = std::time::Duration::from_secs(cfg.transport_poll_timeout_secs);
|
||||
let out_id_cloned = out_id.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let start = std::time::Instant::now();
|
||||
let client = match MyceliumClient::new(base_url) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
let _ = service_poll
|
||||
.append_message_logs(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
vec![format!("MyceliumClient init error: {e}")],
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut last_status: Option<TransportStatus> = Some(TransportStatus::Sent);
|
||||
|
||||
loop {
|
||||
if start.elapsed() >= poll_timeout {
|
||||
let _ = service_poll
|
||||
.append_message_logs(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
vec!["Transport-status polling timed out".to_string()],
|
||||
)
|
||||
.await;
|
||||
// leave last known status; do not override
|
||||
break;
|
||||
}
|
||||
|
||||
match client.message_status(&out_id_cloned).await {
|
||||
Ok(s) => {
|
||||
if last_status.as_ref() != Some(&s) {
|
||||
let _ = service_poll
|
||||
.update_message_transport(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
None,
|
||||
Some(s.clone()),
|
||||
)
|
||||
.await;
|
||||
last_status = Some(s.clone());
|
||||
}
|
||||
|
||||
// Stop on terminal states
|
||||
if matches!(s, TransportStatus::Delivered | TransportStatus::Read) {
|
||||
break;
|
||||
}
|
||||
if matches!(s, TransportStatus::Failed) {
|
||||
let _ = service_poll
|
||||
.append_message_logs(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
vec![format!(
|
||||
"Transport failed for outbound id {out_id_cloned}"
|
||||
)],
|
||||
)
|
||||
.await;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// Log and continue polling
|
||||
let _ = service_poll
|
||||
.append_message_logs(
|
||||
context_id,
|
||||
caller_id,
|
||||
id,
|
||||
vec![format!("messageStatus query error: {e}")],
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
tokio::time::sleep(poll_interval).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user