use std::collections::HashMap;
use crate::{
prepare_command,
resp::{
cmd, ArgsOrCollection, CommandArg, CommandArgs, FromKeyValueValueArray, FromValue,
HashMapExt, IntoArgs, KeyValueArgOrCollection, Value,
},
PreparedCommand, Result,
};
pub trait SentinelCommands {
#[must_use]
fn sentinel_config_get<N, RN, RV, R>(&mut self, name: N) -> PreparedCommand<Self, R>
where
Self: Sized,
N: Into<CommandArg>,
RN: FromValue,
RV: FromValue,
R: FromKeyValueValueArray<RN, RV>,
{
prepare_command(self, cmd("SENTINEL").arg("CONFIG").arg("GET").arg(name))
}
#[must_use]
fn sentinel_config_set<N, V>(&mut self, name: N, value: V) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
V: Into<CommandArg>,
{
prepare_command(
self,
cmd("SENTINEL")
.arg("CONFIG")
.arg("SET")
.arg(name)
.arg(value),
)
}
#[must_use]
fn sentinel_ckquorum<N>(&mut self, master_name: N) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("CKQUORUM").arg(master_name))
}
#[must_use]
fn sentinel_failover<N>(&mut self, master_name: N) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("FAILOVER").arg(master_name))
}
#[must_use]
fn sentinel_flushconfig(&mut self) -> PreparedCommand<Self, ()>
where
Self: Sized,
{
prepare_command(self, cmd("SENTINEL").arg("FLUSHCONFIG"))
}
#[must_use]
fn sentinel_get_master_addr_by_name<N>(
&mut self,
master_name: N,
) -> PreparedCommand<Self, Option<(String, u16)>>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(
self,
cmd("SENTINEL")
.arg("GET-MASTER-ADDR-BY-NAME")
.arg(master_name),
)
}
#[must_use]
fn sentinel_info_cache<N, NN, R>(&mut self, master_names: NN) -> PreparedCommand<Self, R>
where
Self: Sized,
N: Into<CommandArg>,
NN: ArgsOrCollection<N>,
R: FromKeyValueValueArray<String, Vec<(u64, String)>>,
{
prepare_command(self, cmd("SENTINEL").arg("INFO-CACHE").arg(master_names))
}
#[must_use]
fn sentinel_master<N>(&mut self, master_name: N) -> PreparedCommand<Self, SentinelMasterInfo>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("MASTER").arg(master_name))
}
#[must_use]
fn sentinel_masters(&mut self) -> PreparedCommand<Self, Vec<SentinelMasterInfo>>
where
Self: Sized,
{
prepare_command(self, cmd("SENTINEL").arg("MASTERS"))
}
#[must_use]
fn sentinel_monitor<N, I>(
&mut self,
name: N,
ip: I,
port: u16,
quorum: usize,
) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
I: Into<CommandArg>,
{
prepare_command(
self,
cmd("SENTINEL")
.arg("MONITOR")
.arg(name)
.arg(ip)
.arg(port)
.arg(quorum),
)
}
#[must_use]
fn sentinel_remove<N>(&mut self, name: N) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("REMOVE").arg(name))
}
#[must_use]
fn sentinel_set<N, O, V, C>(&mut self, name: N, configs: C) -> PreparedCommand<Self, ()>
where
Self: Sized,
N: Into<CommandArg>,
O: Into<CommandArg>,
V: Into<CommandArg>,
C: KeyValueArgOrCollection<O, V>,
{
prepare_command(self, cmd("SENTINEL").arg("SET").arg(name).arg(configs))
}
#[must_use]
fn sentinel_myid(&mut self) -> PreparedCommand<Self, String>
where
Self: Sized,
{
prepare_command(self, cmd("SENTINEL").arg("MYID"))
}
#[must_use]
fn sentinel_pending_scripts(&mut self) -> PreparedCommand<Self, Vec<Value>>
where
Self: Sized,
{
prepare_command(self, cmd("SENTINEL").arg("PENDING-SCRIPTS"))
}
#[must_use]
fn sentinel_replicas<N>(
&mut self,
master_name: N,
) -> PreparedCommand<Self, Vec<SentinelReplicaInfo>>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("REPLICAS").arg(master_name))
}
#[must_use]
fn sentinel_reset<P>(&mut self, pattern: P) -> PreparedCommand<Self, usize>
where
Self: Sized,
P: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("RESET").arg(pattern))
}
#[must_use]
fn sentinel_sentinels<N>(&mut self, master_name: N) -> PreparedCommand<Self, Vec<SentinelInfo>>
where
Self: Sized,
N: Into<CommandArg>,
{
prepare_command(self, cmd("SENTINEL").arg("SENTINELS").arg(master_name))
}
#[must_use]
fn sentinel_simulate_failure(
&mut self,
mode: SentinelSimulateFailureMode,
) -> PreparedCommand<Self, ()>
where
Self: Sized,
{
prepare_command(self, cmd("SENTINEL").arg("SIMULATE-FAILURE").arg(mode))
}
}
#[derive(Debug)]
pub struct SentinelMasterInfo {
pub name: String,
pub ip: String,
pub port: u16,
pub runid: String,
pub flags: String,
pub link_pending_commands: usize,
pub link_refcount: usize,
pub last_ping_sent: usize,
pub last_ok_ping_reply: usize,
pub last_ping_reply: usize,
pub down_after_milliseconds: u64,
pub info_refresh: u64,
pub role_reported: String,
pub role_reported_time: u64,
pub config_epoch: usize,
pub num_slaves: usize,
pub num_other_sentinels: usize,
pub quorum: usize,
pub failover_timeout: u64,
pub parallel_syncs: usize,
}
impl FromValue for SentinelMasterInfo {
fn from_value(value: Value) -> Result<Self> {
let mut values: HashMap<String, Value> = value.into()?;
Ok(Self {
name: values.remove_or_default("name").into()?,
ip: values.remove_or_default("ip").into()?,
port: values.remove_or_default("port").into()?,
runid: values.remove_or_default("runid").into()?,
flags: values.remove_or_default("flags").into()?,
link_pending_commands: values.remove_or_default("link-pending-commands").into()?,
link_refcount: values.remove_or_default("link-refcount").into()?,
last_ping_sent: values.remove_or_default("last-ping-sent").into()?,
last_ok_ping_reply: values.remove_or_default("last-ok-ping-reply").into()?,
last_ping_reply: values.remove_or_default("last-ping-reply").into()?,
down_after_milliseconds: values.remove_or_default("down-after-milliseconds").into()?,
info_refresh: values.remove_or_default("info-refresh").into()?,
role_reported: values.remove_or_default("role-reported").into()?,
role_reported_time: values.remove_or_default("role-reported-time").into()?,
config_epoch: values.remove_or_default("config-epoch").into()?,
num_slaves: values.remove_or_default("num-slaves").into()?,
num_other_sentinels: values.remove_or_default("num-other-sentinels").into()?,
quorum: values.remove_or_default("quorum").into()?,
failover_timeout: values.remove_or_default("failover-timeout").into()?,
parallel_syncs: values.remove_or_default("parallel-syncs").into()?,
})
}
}
#[derive(Debug)]
pub struct SentinelReplicaInfo {
pub name: String,
pub ip: String,
pub port: u16,
pub runid: String,
pub flags: String,
pub link_pending_commands: usize,
pub link_refcount: usize,
pub last_ping_sent: usize,
pub last_ok_ping_reply: usize,
pub last_ping_reply: usize,
pub down_after_milliseconds: u64,
pub info_refresh: u64,
pub role_reported: String,
pub role_reported_time: u64,
pub master_link_down_time: u64,
pub master_link_status: String,
pub master_host: String,
pub master_port: u16,
pub slave_priority: u64,
pub slave_replica_offset: u64,
pub replica_announed: usize,
}
impl FromValue for SentinelReplicaInfo {
fn from_value(value: Value) -> Result<Self> {
let mut values: HashMap<String, Value> = value.into()?;
Ok(Self {
name: values.remove_or_default("name").into()?,
ip: values.remove_or_default("ip").into()?,
port: values.remove_or_default("port").into()?,
runid: values.remove_or_default("runid").into()?,
flags: values.remove_or_default("flags").into()?,
link_pending_commands: values.remove_or_default("link-pending-commands").into()?,
link_refcount: values.remove_or_default("link-refcount").into()?,
last_ping_sent: values.remove_or_default("last-ping-sent").into()?,
last_ok_ping_reply: values.remove_or_default("last-ok-ping-reply").into()?,
last_ping_reply: values.remove_or_default("last-ping-reply").into()?,
down_after_milliseconds: values.remove_or_default("down-after-milliseconds").into()?,
info_refresh: values.remove_or_default("info-refresh").into()?,
role_reported: values.remove_or_default("role-reported").into()?,
role_reported_time: values.remove_or_default("role-reported-time").into()?,
master_link_down_time: values.remove_or_default("master-link-down-time").into()?,
master_link_status: values.remove_or_default("master-link-status").into()?,
master_host: values.remove_or_default("master-host").into()?,
master_port: values.remove_or_default("master-port").into()?,
slave_priority: values.remove_or_default("slave-priority").into()?,
slave_replica_offset: values.remove_or_default("slave-replica-offset").into()?,
replica_announed: values.remove_or_default("replica-announed").into()?,
})
}
}
pub struct SentinelInfo {
pub name: String,
pub ip: String,
pub port: u16,
pub runid: String,
pub flags: String,
pub link_pending_commands: usize,
pub link_refcount: usize,
pub last_ping_sent: usize,
pub last_ok_ping_reply: usize,
pub last_ping_reply: usize,
pub down_after_milliseconds: u64,
pub last_hello_message: u64,
pub voted_leader: String,
pub voted_leader_epoch: usize,
}
impl FromValue for SentinelInfo {
fn from_value(value: Value) -> Result<Self> {
let mut values: HashMap<String, Value> = value.into()?;
Ok(Self {
name: values.remove_or_default("name").into()?,
ip: values.remove_or_default("ip").into()?,
port: values.remove_or_default("port").into()?,
runid: values.remove_or_default("runid").into()?,
flags: values.remove_or_default("flags").into()?,
link_pending_commands: values.remove_or_default("link-pending-commands").into()?,
link_refcount: values.remove_or_default("link-refcount").into()?,
last_ping_sent: values.remove_or_default("last-ping-sent").into()?,
last_ok_ping_reply: values.remove_or_default("last-ok-ping-reply").into()?,
last_ping_reply: values.remove_or_default("last-ping-reply").into()?,
down_after_milliseconds: values.remove_or_default("down-after-milliseconds").into()?,
last_hello_message: values.remove_or_default("last-hello-message").into()?,
voted_leader: values.remove_or_default("voted-leader").into()?,
voted_leader_epoch: values.remove_or_default("voted-leader-epoch").into()?,
})
}
}
pub enum SentinelSimulateFailureMode {
CrashAfterElection,
CrashAfterPromotion,
}
impl IntoArgs for SentinelSimulateFailureMode {
fn into_args(self, args: CommandArgs) -> CommandArgs {
args.arg(match self {
SentinelSimulateFailureMode::CrashAfterElection => "CRASH-AFTER-ELECTION",
SentinelSimulateFailureMode::CrashAfterPromotion => "CRASH-AFTER-PROMOTION",
})
}
}