Listen for responses of supervisors

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2025-09-04 16:24:15 +02:00
parent c6077623b0
commit 059d5131e7
6 changed files with 423 additions and 8 deletions

View File

@@ -99,6 +99,16 @@ impl SupervisorClient {
})
}
/// Build a supervisor JSON-RPC payload but force a specific id (used for correlation).
fn build_supervisor_payload_with_id(&self, method: &str, params: Value, id: u64) -> Value {
json!({
"jsonrpc": "2.0",
"id": id,
"method": method,
"params": params,
})
}
fn encode_payload(payload: &Value) -> Result<String, SupervisorClientError> {
let s = serde_json::to_string(payload)?;
Ok(BASE64_STANDARD.encode(s.as_bytes()))
@@ -147,6 +157,42 @@ impl SupervisorClient {
)))
}
/// Variant of call that also returns the inner supervisor JSON-RPC id used in the payload.
/// This id is required to correlate asynchronous popMessage replies coming from Mycelium.
pub async fn call_with_ids(
&self,
method: &str,
params: Value,
) -> Result<(String, u64), SupervisorClientError> {
let inner_id = self.next_id();
let inner = self.build_supervisor_payload_with_id(method, params, inner_id);
let payload_b64 = Self::encode_payload(&inner)?;
let result = self
.mycelium
.push_message(
&self.destination,
&Self::encode_topic(self.topic.as_bytes()),
&payload_b64,
None,
)
.await?;
let out_id = if let Some(id) = MyceliumClient::extract_message_id_from_result(&result) {
id
} else if let Some(arr) = result.as_array()
&& arr.len() == 1
&& let Some(id) = MyceliumClient::extract_message_id_from_result(&arr[0])
{
id
} else {
return Err(SupervisorClientError::InvalidResponse(format!(
"result did not contain message id: {result}"
)));
};
Ok((out_id, inner_id))
}
/// Synchronous variant: wait for a JSON-RPC reply via Mycelium reply_timeout, and return the inner JSON-RPC "result".
/// If the supervisor returns an error object, map to RpcError.
pub async fn call_sync(
@@ -308,6 +354,19 @@ impl SupervisorClient {
self.call("job.run", params).await
}
/// Typed wrapper returning both outbound Mycelium id and inner supervisor JSON-RPC id.
pub async fn job_run_with_ids(
&self,
job: Value,
) -> Result<(String, u64), SupervisorClientError> {
let secret = self.need_secret()?;
let params = json!([{
"secret": secret,
"job": job
}]);
self.call_with_ids("job.run", params).await
}
pub async fn job_start(
&self,
job_id: impl Into<String>,