Listen for responses of supervisors
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
@@ -3,6 +3,8 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use reqwest::Client as HttpClient;
|
||||
|
||||
use base64::Engine;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
|
||||
use serde_json::{Value, json};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -159,6 +161,83 @@ impl MyceliumClient {
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.to_string())
|
||||
}
|
||||
/// popMessage: retrieve an inbound message if available (optionally filtered by topic).
|
||||
/// - peek: if true, do not remove the message from the queue
|
||||
/// - timeout_secs: seconds to wait for a message (0 returns immediately)
|
||||
/// - topic_plain: optional plain-text topic which will be base64-encoded per Mycelium spec
|
||||
/// Returns:
|
||||
/// - Ok(Some(result_json)) on success, where result_json matches InboundMessage schema
|
||||
/// - Ok(None) when there is no message ready (Mycelium returns error code 204)
|
||||
pub async fn pop_message(
|
||||
&self,
|
||||
peek: Option<bool>,
|
||||
timeout_secs: Option<u64>,
|
||||
topic_plain: Option<&str>,
|
||||
) -> Result<Option<Value>, MyceliumClientError> {
|
||||
// Build params array
|
||||
let mut params_array = vec![];
|
||||
if let Some(p) = peek {
|
||||
params_array.push(serde_json::Value::Bool(p));
|
||||
} else {
|
||||
params_array.push(serde_json::Value::Null)
|
||||
}
|
||||
if let Some(t) = timeout_secs {
|
||||
params_array.push(serde_json::Value::Number(t.into()));
|
||||
} else {
|
||||
params_array.push(serde_json::Value::Null)
|
||||
}
|
||||
if let Some(tp) = topic_plain {
|
||||
let topic_b64 = BASE64_STANDARD.encode(tp.as_bytes());
|
||||
params_array.push(serde_json::Value::String(topic_b64));
|
||||
} else {
|
||||
params_array.push(serde_json::Value::Null)
|
||||
}
|
||||
|
||||
let req = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": self.next_id(),
|
||||
"method": "popMessage",
|
||||
"params": serde_json::Value::Array(params_array),
|
||||
});
|
||||
|
||||
tracing::info!(%req, "calling popMessage");
|
||||
|
||||
let resp = self.http.post(&self.base_url).json(&req).send().await?;
|
||||
let status = resp.status();
|
||||
let body: Value = resp.json().await?;
|
||||
|
||||
// Handle JSON-RPC error envelope specially for code 204 (no message ready)
|
||||
if let Some(err) = body.get("error") {
|
||||
let code = err.get("code").and_then(|v| v.as_i64()).unwrap_or(0);
|
||||
let msg = err
|
||||
.get("message")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("unknown error");
|
||||
|
||||
if code == 204 {
|
||||
// No message ready
|
||||
return Ok(None);
|
||||
}
|
||||
if code == 408 {
|
||||
// Align with other transport timeout mapping
|
||||
return Err(MyceliumClientError::TransportTimeout);
|
||||
}
|
||||
return Err(MyceliumClientError::RpcError(format!(
|
||||
"code={code} msg={msg}"
|
||||
)));
|
||||
}
|
||||
|
||||
if !status.is_success() {
|
||||
return Err(MyceliumClientError::RpcError(format!(
|
||||
"HTTP {status}, body {body}"
|
||||
)));
|
||||
}
|
||||
|
||||
let result = body.get("result").ok_or_else(|| {
|
||||
MyceliumClientError::InvalidResponse(format!("missing result in response: {body}"))
|
||||
})?;
|
||||
Ok(Some(result.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Reference in New Issue
Block a user