use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NodeRole {
Gateway,
Function,
Worker,
Scheduler,
}
impl NodeRole {
pub fn as_str(&self) -> &'static str {
match self {
Self::Gateway => "gateway",
Self::Function => "function",
Self::Worker => "worker",
Self::Scheduler => "scheduler",
}
}
pub fn all() -> Vec<Self> {
vec![Self::Gateway, Self::Function, Self::Worker, Self::Scheduler]
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseNodeRoleError(pub String);
impl std::fmt::Display for ParseNodeRoleError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "invalid node role: {}", self.0)
}
}
impl std::error::Error for ParseNodeRoleError {}
impl FromStr for NodeRole {
type Err = ParseNodeRoleError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"gateway" => Ok(Self::Gateway),
"function" => Ok(Self::Function),
"worker" => Ok(Self::Worker),
"scheduler" => Ok(Self::Scheduler),
_ => Err(ParseNodeRoleError(s.to_string())),
}
}
}
impl std::fmt::Display for NodeRole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LeaderRole {
Scheduler,
MetricsAggregator,
LogCompactor,
}
impl LeaderRole {
pub fn lock_id(&self) -> i64 {
match self {
Self::Scheduler => 0x464F_5247_0001,
Self::MetricsAggregator => 0x464F_5247_0002,
Self::LogCompactor => 0x464F_5247_0003,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Scheduler => "scheduler",
Self::MetricsAggregator => "metrics_aggregator",
Self::LogCompactor => "log_compactor",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseLeaderRoleError(pub String);
impl std::fmt::Display for ParseLeaderRoleError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "invalid leader role: {}", self.0)
}
}
impl std::error::Error for ParseLeaderRoleError {}
impl FromStr for LeaderRole {
type Err = ParseLeaderRoleError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"scheduler" => Ok(Self::Scheduler),
"metrics_aggregator" => Ok(Self::MetricsAggregator),
"log_compactor" => Ok(Self::LogCompactor),
_ => Err(ParseLeaderRoleError(s.to_string())),
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
mod tests {
use super::*;
#[test]
fn test_node_role_conversion() {
assert_eq!("gateway".parse::<NodeRole>(), Ok(NodeRole::Gateway));
assert_eq!("worker".parse::<NodeRole>(), Ok(NodeRole::Worker));
assert!("invalid".parse::<NodeRole>().is_err());
assert_eq!(NodeRole::Gateway.as_str(), "gateway");
}
#[test]
fn test_all_roles() {
let roles = NodeRole::all();
assert_eq!(roles.len(), 4);
assert!(roles.contains(&NodeRole::Gateway));
assert!(roles.contains(&NodeRole::Scheduler));
}
#[test]
fn test_leader_role_lock_ids() {
let scheduler_id = LeaderRole::Scheduler.lock_id();
let metrics_id = LeaderRole::MetricsAggregator.lock_id();
let log_id = LeaderRole::LogCompactor.lock_id();
assert_ne!(scheduler_id, metrics_id);
assert_ne!(metrics_id, log_id);
assert_ne!(scheduler_id, log_id);
}
#[test]
fn test_leader_role_conversion() {
assert_eq!("scheduler".parse::<LeaderRole>(), Ok(LeaderRole::Scheduler));
assert!("invalid".parse::<LeaderRole>().is_err());
assert_eq!(LeaderRole::Scheduler.as_str(), "scheduler");
}
}