Skip to main content

nodedb_cluster/rpc_codec/
metadata.rs

1//! MetadataProposeRequest / MetadataProposeResponse wire types and codecs.
2
3use super::discriminants::*;
4use super::header::write_frame;
5use super::raft_rpc::RaftRpc;
6use crate::error::{ClusterError, Result};
7
8/// Forward an opaque metadata-group proposal payload to the metadata-group leader.
9#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
10pub struct MetadataProposeRequest {
11    pub bytes: Vec<u8>,
12}
13
14/// Response to a forwarded metadata-group proposal.
15#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
16pub struct MetadataProposeResponse {
17    pub success: bool,
18    pub log_index: u64,
19    pub leader_hint: Option<u64>,
20    pub error_message: String,
21}
22
23impl MetadataProposeResponse {
24    pub fn ok(log_index: u64) -> Self {
25        Self {
26            success: true,
27            log_index,
28            leader_hint: None,
29            error_message: String::new(),
30        }
31    }
32
33    pub fn err(message: impl Into<String>, leader_hint: Option<u64>) -> Self {
34        Self {
35            success: false,
36            log_index: 0,
37            leader_hint,
38            error_message: message.into(),
39        }
40    }
41}
42
43macro_rules! to_bytes {
44    ($msg:expr) => {
45        rkyv::to_bytes::<rkyv::rancor::Error>($msg)
46            .map(|b| b.to_vec())
47            .map_err(|e| ClusterError::Codec {
48                detail: format!("rkyv serialize: {e}"),
49            })
50    };
51}
52
53macro_rules! from_bytes {
54    ($payload:expr, $T:ty, $name:expr) => {{
55        let mut aligned = rkyv::util::AlignedVec::<16>::with_capacity($payload.len());
56        aligned.extend_from_slice($payload);
57        rkyv::from_bytes::<$T, rkyv::rancor::Error>(&aligned).map_err(|e| ClusterError::Codec {
58            detail: format!("rkyv deserialize {}: {e}", $name),
59        })
60    }};
61}
62
63pub(super) fn encode_metadata_propose_req(
64    msg: &MetadataProposeRequest,
65    out: &mut Vec<u8>,
66) -> Result<()> {
67    write_frame(RPC_METADATA_PROPOSE_REQ, &to_bytes!(msg)?, out)
68}
69pub(super) fn encode_metadata_propose_resp(
70    msg: &MetadataProposeResponse,
71    out: &mut Vec<u8>,
72) -> Result<()> {
73    write_frame(RPC_METADATA_PROPOSE_RESP, &to_bytes!(msg)?, out)
74}
75
76pub(super) fn decode_metadata_propose_req(payload: &[u8]) -> Result<RaftRpc> {
77    Ok(RaftRpc::MetadataProposeRequest(from_bytes!(
78        payload,
79        MetadataProposeRequest,
80        "MetadataProposeRequest"
81    )?))
82}
83pub(super) fn decode_metadata_propose_resp(payload: &[u8]) -> Result<RaftRpc> {
84    Ok(RaftRpc::MetadataProposeResponse(from_bytes!(
85        payload,
86        MetadataProposeResponse,
87        "MetadataProposeResponse"
88    )?))
89}