pub(crate) mod server_connection;
pub(crate) mod server_manager;
pub mod server_routing;
pub mod server_version;
use crate::common::address::{Address, address_translation::AddressTranslation};
pub const DEFAULT_SERVER_ID: u64 = 0;
pub trait Replica: Clone {
fn id(&self) -> u64;
fn role(&self) -> Option<ReplicationRole>;
fn is_primary(&self) -> bool;
fn term(&self) -> Option<u64>;
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Server {
Available(AvailableServer),
Unavailable { replication_status: Option<ReplicationStatus> },
}
impl Server {
pub(crate) fn available_from_private(
private_address: Address,
replication_status: Option<ReplicationStatus>,
) -> Self {
Self::Available(AvailableServer::from_private(private_address, replication_status))
}
pub(crate) fn translate_address(&mut self, address_translation: &AddressTranslation) {
match self {
Server::Available(available) => available.translate_address(address_translation),
Server::Unavailable { .. } => {}
}
}
pub(crate) fn translated(mut self, address_translation: &AddressTranslation) -> Self {
self.translate_address(address_translation);
self
}
pub(crate) fn replication_status(&self) -> &Option<ReplicationStatus> {
match self {
Server::Available(available_server) => available_server.replication_status(),
Server::Unavailable { replication_status } => replication_status,
}
}
pub fn address(&self) -> Option<&Address> {
match self {
Server::Available(available_server) => Some(available_server.address()),
Server::Unavailable { .. } => None,
}
}
}
impl Replica for Server {
fn id(&self) -> u64 {
self.replication_status().map(|status| status.id).unwrap_or(DEFAULT_SERVER_ID)
}
fn role(&self) -> Option<ReplicationRole> {
self.replication_status().map(|status| status.role).flatten()
}
fn is_primary(&self) -> bool {
matches!(self.role(), Some(ReplicationRole::Primary))
}
fn term(&self) -> Option<u64> {
self.replication_status().map(|status| status.term).flatten()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct AvailableServer {
private_address: Address,
public_address: Option<Address>,
replication_status: Option<ReplicationStatus>,
}
impl AvailableServer {
pub(crate) fn from_private(private_address: Address, replication_status: Option<ReplicationStatus>) -> Self {
Self { private_address, public_address: None, replication_status }
}
pub(crate) fn translate_address(&mut self, address_translation: &AddressTranslation) {
if let Some(translated) = address_translation.to_public(&self.private_address) {
self.public_address = Some(translated);
}
}
pub(crate) fn translated(mut self, address_translation: &AddressTranslation) -> Self {
self.translate_address(address_translation);
self
}
pub(crate) fn private_address(&self) -> &Address {
&self.private_address
}
pub(crate) fn replication_status(&self) -> &Option<ReplicationStatus> {
&self.replication_status
}
pub fn address(&self) -> &Address {
self.public_address.as_ref().unwrap_or_else(|| &self.private_address)
}
}
impl Replica for AvailableServer {
fn id(&self) -> u64 {
self.replication_status().map(|status| status.id).unwrap_or(DEFAULT_SERVER_ID)
}
fn role(&self) -> Option<ReplicationRole> {
self.replication_status().map(|status| status.role).flatten()
}
fn is_primary(&self) -> bool {
matches!(self.role(), Some(ReplicationRole::Primary))
}
fn term(&self) -> Option<u64> {
self.replication_status().map(|status| status.term).flatten()
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct ReplicationStatus {
pub(crate) id: u64,
pub(crate) role: Option<ReplicationRole>,
pub(crate) term: Option<u64>,
}
impl Default for ReplicationStatus {
fn default() -> Self {
Self { id: DEFAULT_SERVER_ID, role: None, term: None }
}
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub enum ReplicationRole {
Primary,
Candidate,
Secondary,
}