use openraft::BasicNode;
use openraft::EntryPayload;
use openraft::LogId;
use openraft::Membership;
use openraft::entry::RaftEntry;
use openraft::entry::RaftPayload;
use openraft::log_id::RaftLogId;
use openraft::vote::leader_id_std::CommittedLeaderId;
use crate::app::EzApp;
pub type EzLogId = (u64, u64);
pub type EzCommittedLeaderId = CommittedLeaderId<u64>;
type EzEntryPayload<T> = EntryPayload<<T as EzApp>::Request, u64, BasicNode>;
#[derive(serde::Deserialize, serde::Serialize)]
#[serde(bound = "")]
pub struct EzEntry<T>
where T: EzApp
{
pub log_id: EzLogId,
pub payload: EzEntryPayload<T>,
}
impl<T> Clone for EzEntry<T>
where T: EzApp
{
fn clone(&self) -> Self {
Self {
log_id: self.log_id,
payload: self.payload.clone(),
}
}
}
impl<T> std::fmt::Debug for EzEntry<T>
where T: EzApp
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EzEntry").field("log_id", &self.log_id).field("payload", &self.payload).finish()
}
}
impl<T> std::fmt::Display for EzEntry<T>
where T: EzApp
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"EzEntry(log_id: ({}, {}), payload: {:?})",
self.log_id.0, self.log_id.1, self.payload
)
}
}
impl<T> RaftPayload<u64, BasicNode> for EzEntry<T>
where T: EzApp
{
fn get_membership(&self) -> Option<Membership<u64, BasicNode>> {
self.payload.get_membership()
}
}
impl<T> RaftEntry for EzEntry<T>
where T: EzApp
{
type CommittedLeaderId = EzCommittedLeaderId;
type D = T::Request;
type NodeId = u64;
type Node = BasicNode;
fn new(log_id: LogId<EzCommittedLeaderId>, payload: EzEntryPayload<T>) -> Self {
Self {
log_id: log_id.to_type(),
payload,
}
}
fn log_id_parts(&self) -> (&EzCommittedLeaderId, u64) {
RaftLogId::log_id_parts(&self.log_id)
}
fn set_log_id(&mut self, new: LogId<EzCommittedLeaderId>) {
self.log_id = new.to_type();
}
}
#[cfg(test)]
mod tests {
use async_trait::async_trait;
use super::*;
#[derive(serde::Deserialize, serde::Serialize)]
struct Marker;
#[async_trait]
impl EzApp for Marker {
type Request = String;
type Response = String;
async fn apply(&mut self, req: String) -> String {
req
}
}
#[test]
fn ez_entry_clones_without_t_clone() {
let entry = EzEntry::<Marker> {
log_id: (7, 9),
payload: EntryPayload::Normal("hello".to_string()),
};
let clone = entry.clone();
assert_eq!((7, 9), clone.log_id);
let EntryPayload::Normal(req) = clone.payload else {
panic!("payload variant changed by clone");
};
assert_eq!("hello", req);
}
}