Skip to main content

nodedb_cluster/rpc_codec/
metadata.rs

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