use std::io::Cursor;
use serde::{Deserialize, Serialize};
use tsoracle_openraft_toolkit::declare_raft_types_ext;
use crate::log_entry::HighWaterCommand;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct OpenraftPeer {
pub addr: String,
pub service_endpoint: String,
}
pub trait ServiceEndpoint {
fn service_endpoint(&self) -> Option<&str>;
}
impl ServiceEndpoint for OpenraftPeer {
fn service_endpoint(&self) -> Option<&str> {
if self.service_endpoint.is_empty() {
None
} else {
Some(&self.service_endpoint)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HighWaterApplied {
pub value: u64,
}
declare_raft_types_ext! {
pub TypeConfig:
Node = OpenraftPeer,
AppData = HighWaterCommand,
AppDataResponse = HighWaterApplied,
SnapshotData = Cursor<Vec<u8>>,
}
#[doc(hidden)]
pub type OpenraftEntry = openraft::type_config::alias::EntryOf<TypeConfig>;
#[doc(hidden)]
pub type OpenraftVote = openraft::type_config::alias::VoteOf<TypeConfig>;
#[doc(hidden)]
pub type OpenraftLogId = openraft::type_config::alias::LogIdOf<TypeConfig>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn openraft_peer_round_trips() {
let peer = OpenraftPeer {
addr: "10.0.0.1:50051".to_string(),
service_endpoint: String::new(),
};
let bytes = postcard::to_stdvec(&peer).expect("serialize");
let back: OpenraftPeer = postcard::from_bytes(&bytes).expect("deserialize");
assert_eq!(back, peer);
}
#[test]
fn openraft_peer_default_has_all_empty_fields() {
let peer = OpenraftPeer::default();
assert_eq!(peer.addr, "");
assert_eq!(peer.service_endpoint, "");
}
#[test]
fn openraft_peer_round_trips_empty_addr() {
let peer = OpenraftPeer {
addr: String::new(),
service_endpoint: String::new(),
};
let bytes = postcard::to_stdvec(&peer).expect("serialize");
let back: OpenraftPeer = postcard::from_bytes(&bytes).expect("deserialize");
assert_eq!(back, peer);
}
#[test]
fn openraft_peer_pins_field_layout() {
let peer = OpenraftPeer {
addr: "a:1".into(),
service_endpoint: "b:2".into(),
};
let bytes = postcard::to_stdvec(&peer).expect("serialize");
assert_eq!(bytes, vec![3, b'a', b':', b'1', 3, b'b', b':', b'2']);
}
#[test]
fn high_water_applied_round_trips() {
let applied = HighWaterApplied { value: 12_345 };
let bytes = postcard::to_stdvec(&applied).expect("serialize");
let back: HighWaterApplied = postcard::from_bytes(&bytes).expect("deserialize");
assert_eq!(back, applied);
}
#[test]
fn high_water_applied_round_trips_zero_and_max() {
for v in [0u64, u64::MAX] {
let applied = HighWaterApplied { value: v };
let bytes = postcard::to_stdvec(&applied).expect("serialize");
let back: HighWaterApplied = postcard::from_bytes(&bytes).expect("deserialize");
assert_eq!(back, applied);
}
}
#[test]
fn openraft_peer_round_trips_both_fields() {
let peer = OpenraftPeer {
addr: "node-1:50052".to_string(),
service_endpoint: "http://node-1:50051".to_string(),
};
let bytes = postcard::to_stdvec(&peer).expect("serialize");
let back: OpenraftPeer = postcard::from_bytes(&bytes).expect("deserialize");
assert_eq!(back, peer);
}
#[test]
fn service_endpoint_is_some_when_set_none_when_empty() {
use crate::type_config::ServiceEndpoint;
let with = OpenraftPeer {
addr: "node-1:50052".to_string(),
service_endpoint: "http://node-1:50051".to_string(),
};
assert_eq!(with.service_endpoint(), Some("http://node-1:50051"));
let without = OpenraftPeer {
addr: "node-1:50052".to_string(),
service_endpoint: String::new(),
};
assert_eq!(without.service_endpoint(), None);
}
}