use {
super::{KeyspaceError, KeyspaceNode, KeyspaceResult, NodeRef},
std::ops::Deref,
};
pub trait ReplicationStrategy<N>: Clone {
fn is_eligible_replica(&mut self, node: &N) -> bool;
}
#[derive(Debug, Default, Clone, Copy)]
pub struct DefaultReplicationStrategy {}
impl<N> ReplicationStrategy<N> for DefaultReplicationStrategy {
fn is_eligible_replica(&mut self, _node: &N) -> bool {
true
}
}
impl DefaultReplicationStrategy {
pub fn new() -> Self {
Self {}
}
}
#[derive(Debug)]
pub(crate) struct ReplicaSet<N: KeyspaceNode, const RF: usize>([NodeRef<N>; RF]);
impl<N: KeyspaceNode, const RF: usize> Clone for ReplicaSet<N, RF> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<N: KeyspaceNode, const RF: usize> PartialEq for ReplicaSet<N, RF> {
fn eq(&self, other: &Self) -> bool {
if self.0.len() != other.0.len() {
return false;
}
self.0.iter().all(|n| other.0.contains(n))
}
}
impl<N: KeyspaceNode, const RF: usize> Eq for ReplicaSet<N, RF> {}
impl<N: KeyspaceNode, const RF: usize> Deref for ReplicaSet<N, RF> {
type Target = [NodeRef<N>; RF];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<N: KeyspaceNode, const RF: usize> ReplicaSet<N, RF> {
pub fn try_from_iter<I: IntoIterator<Item = NodeRef<N>>>(iter: I) -> KeyspaceResult<Self> {
use std::array::from_fn;
let mut iter = iter.into_iter();
let mut count = 0;
let items: [NodeRef<N>; RF] = from_fn(|_| {
iter.next()
.and_then(|item| {
count += 1;
Some(item)
})
.unwrap_or_default()
});
if count < RF {
return Err(KeyspaceError::IncompleteReplicaSet);
}
Ok(ReplicaSet(items))
}
}