use crate::microsvc::{CommandRequest, CommandResponse};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
pub const COMMAND_DISPATCH_ENVELOPE_VERSION: u32 = 1;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommandDispatchEnvelope {
pub version: u32,
pub command: String,
pub input: serde_json::Value,
#[serde(default)]
pub session_variables: BTreeMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub command_fingerprint: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub idempotency_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub causation_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deadline_unix_ms: Option<u64>,
}
impl CommandDispatchEnvelope {
pub fn from_request(request: &CommandRequest) -> Self {
let mut session_variables = BTreeMap::new();
for (key, value) in &request.session_variables {
session_variables.insert(key.clone(), value.clone());
}
Self {
version: COMMAND_DISPATCH_ENVELOPE_VERSION,
command: request.command.clone(),
input: request.input.clone(),
session_variables,
command_fingerprint: None,
idempotency_key: None,
causation_id: None,
deadline_unix_ms: None,
}
}
pub fn into_request(self) -> Result<CommandRequest, String> {
if self.version != COMMAND_DISPATCH_ENVELOPE_VERSION {
return Err(format!(
"unsupported command dispatch envelope version {}",
self.version
));
}
Ok(CommandRequest {
command: self.command,
input: self.input,
session_variables: self.session_variables.into_iter().collect(),
})
}
pub fn canonical_bytes(&self) -> Result<Vec<u8>, serde_json::Error> {
serde_json::to_vec(self)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CommandDispatchReceipt {
pub command: String,
pub status: u16,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub causation_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub idempotency_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ledger_id: Option<String>,
}
impl CommandDispatchReceipt {
pub fn from_response(command: &str, response: &CommandResponse) -> Self {
Self {
command: command.to_string(),
status: response.status,
causation_id: None,
idempotency_key: None,
ledger_id: None,
}
}
}