From 7e540929904d83dbca6d883c7a3b358ebff4f67d Mon Sep 17 00:00:00 2001 From: Georgy Moshkin <gmoshkin@picodata.io> Date: Wed, 21 Dec 2022 12:13:49 +0300 Subject: [PATCH] refactor(failure_domain): extract mod failure_domain --- src/args.rs | 2 +- src/failure_domain.rs | 85 ++++++++++++++++++++++++++++++++ src/instance.rs | 2 +- src/main.rs | 1 + src/storage.rs | 6 ++- src/traft/mod.rs | 84 ------------------------------- src/traft/rpc/join.rs | 3 +- src/traft/rpc/update_instance.rs | 2 +- src/traft/topology.rs | 4 +- 9 files changed, 97 insertions(+), 92 deletions(-) create mode 100644 src/failure_domain.rs diff --git a/src/args.rs b/src/args.rs index 82d79b79b7..3b65305443 100644 --- a/src/args.rs +++ b/src/args.rs @@ -7,9 +7,9 @@ use tarantool::log::SayLevel; use tarantool::tlua; use thiserror::Error; +use crate::failure_domain::FailureDomain; use crate::instance::InstanceId; use crate::replicaset::ReplicasetId; -use crate::traft::FailureDomain; use crate::util::Uppercase; #[derive(Debug, Parser)] diff --git a/src/failure_domain.rs b/src/failure_domain.rs new file mode 100644 index 0000000000..85e9dfb645 --- /dev/null +++ b/src/failure_domain.rs @@ -0,0 +1,85 @@ +use crate::stringify_debug; +use crate::util::Uppercase; +use std::collections::HashMap; + +//////////////////////////////////////////////////////////////////////////////// +/// Failure domains of a given instance. +#[derive(Default, PartialEq, Eq, Clone, serde::Deserialize, serde::Serialize)] +pub struct FailureDomain { + #[serde(flatten)] + data: HashMap<Uppercase, Uppercase>, +} + +impl FailureDomain { + pub fn contains_name(&self, name: &Uppercase) -> bool { + self.data.contains_key(name) + } + + pub fn names(&self) -> std::collections::hash_map::Keys<Uppercase, Uppercase> { + self.data.keys() + } + + /// Empty `FailureDomain` doesn't intersect with any other `FailureDomain` + /// even with another empty one. + pub fn intersects(&self, other: &Self) -> bool { + for (name, value) in &self.data { + match other.data.get(name) { + Some(other_value) if value == other_value => { + return true; + } + _ => {} + } + } + false + } +} + +impl std::fmt::Display for FailureDomain { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("{")?; + let mut iter = self.data.iter(); + if let Some((k, v)) = iter.next() { + write!(f, "{k}: {v}")?; + for (k, v) in iter { + write!(f, ", {k}: {v}")?; + } + } + f.write_str("}")?; + Ok(()) + } +} + +impl std::fmt::Debug for FailureDomain { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let mut ds = f.debug_struct(stringify_debug!(FailureDomain)); + for (name, value) in &self.data { + ds.field(name, &**value); + } + ds.finish() + } +} + +impl<I, K, V> From<I> for FailureDomain +where + I: IntoIterator<Item = (K, V)>, + Uppercase: From<K>, + Uppercase: From<V>, +{ + fn from(data: I) -> Self { + Self { + data: data + .into_iter() + .map(|(k, v)| (Uppercase::from(k), Uppercase::from(v))) + .collect(), + } + } +} + +impl<'a> IntoIterator for &'a FailureDomain { + type IntoIter = <&'a HashMap<Uppercase, Uppercase> as IntoIterator>::IntoIter; + type Item = <&'a HashMap<Uppercase, Uppercase> as IntoIterator>::Item; + + fn into_iter(self) -> Self::IntoIter { + self.data.iter() + } +} diff --git a/src/instance.rs b/src/instance.rs index 898b489d85..911211d768 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -1,6 +1,6 @@ +use super::failure_domain::FailureDomain; use super::replicaset::ReplicasetId; use crate::has_grades; -use crate::traft::FailureDomain; use crate::traft::RaftId; use crate::util::Transition; use ::serde::{Deserialize, Serialize}; diff --git a/src/main.rs b/src/main.rs index 05a0baf3d3..ddad33dafe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ use traft::error::Error; mod app; mod args; mod discovery; +mod failure_domain; mod governor; mod instance; mod ipc; diff --git a/src/storage.rs b/src/storage.rs index 719921b183..cd9a5513ca 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -2,6 +2,7 @@ use ::tarantool::index::{Index, IndexIterator, IteratorType}; use ::tarantool::space::{FieldType, Space}; use ::tarantool::tuple::{DecodeOwned, ToTupleBuffer, Tuple}; +use crate::failure_domain as fd; use crate::instance::{self, grade, Instance}; use crate::replicaset::{Replicaset, ReplicasetId}; use crate::traft; @@ -523,7 +524,7 @@ define_instance_fields! { ReplicasetUuid : String = ("replicaset_uuid", FieldType::String) CurrentGrade : grade::CurrentGrade = ("current_grade", FieldType::Array) TargetGrade : grade::TargetGrade = ("target_grade", FieldType::Array) - FailureDomain : traft::FailureDomain = ("failure_domain", FieldType::Map) + FailureDomain : fd::FailureDomain = ("failure_domain", FieldType::Map) } impl tarantool::tuple::TupleIndex for InstanceField { @@ -764,13 +765,14 @@ inventory::submit!(crate::InnerTest { body: || { use crate::instance::grade::{CurrentGradeVariant as CGV, TargetGradeVariant as TGV}; use crate::instance::InstanceId; + use crate::failure_domain::FailureDomain; let storage_instances = Instances::new().unwrap(); let space_instances = storage_instances.space.clone(); let storage_peer_addresses = PeerAddresses::new().unwrap(); let space_peer_addresses = storage_peer_addresses.space.clone(); - let faildom = crate::traft::FailureDomain::from([("a", "b")]); + let faildom = FailureDomain::from([("a", "b")]); for instance in vec![ // r1 diff --git a/src/traft/mod.rs b/src/traft/mod.rs index 344a9b5bc1..aaddea5b84 100644 --- a/src/traft/mod.rs +++ b/src/traft/mod.rs @@ -12,13 +12,11 @@ pub mod topology; use crate::instance::Instance; use crate::stringify_debug; -use crate::util::Uppercase; use ::raft::prelude as raft; use ::tarantool::tuple::Encode; use op::Op; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; use std::convert::TryFrom; use std::fmt::Debug; use std::result::Result as StdResult; @@ -395,88 +393,6 @@ pub fn replicaset_uuid(replicaset_id: &str) -> String { uuid.hyphenated().to_string() } -//////////////////////////////////////////////////////////////////////////////// -/// Failure domains of a given instance. -#[derive(Default, PartialEq, Eq, Clone, serde::Deserialize, serde::Serialize)] -pub struct FailureDomain { - #[serde(flatten)] - data: HashMap<Uppercase, Uppercase>, -} - -impl FailureDomain { - pub fn contains_name(&self, name: &Uppercase) -> bool { - self.data.contains_key(name) - } - - pub fn names(&self) -> std::collections::hash_map::Keys<Uppercase, Uppercase> { - self.data.keys() - } - - /// Empty `FailureDomain` doesn't intersect with any other `FailureDomain` - /// even with another empty one. - pub fn intersects(&self, other: &Self) -> bool { - for (name, value) in &self.data { - match other.data.get(name) { - Some(other_value) if value == other_value => { - return true; - } - _ => {} - } - } - false - } -} - -impl std::fmt::Display for FailureDomain { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - f.write_str("{")?; - let mut iter = self.data.iter(); - if let Some((k, v)) = iter.next() { - write!(f, "{k}: {v}")?; - for (k, v) in iter { - write!(f, ", {k}: {v}")?; - } - } - f.write_str("}")?; - Ok(()) - } -} - -impl std::fmt::Debug for FailureDomain { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let mut ds = f.debug_struct(stringify_debug!(FailureDomain)); - for (name, value) in &self.data { - ds.field(name, &**value); - } - ds.finish() - } -} - -impl<I, K, V> From<I> for FailureDomain -where - I: IntoIterator<Item = (K, V)>, - Uppercase: From<K>, - Uppercase: From<V>, -{ - fn from(data: I) -> Self { - Self { - data: data - .into_iter() - .map(|(k, v)| (Uppercase::from(k), Uppercase::from(v))) - .collect(), - } - } -} - -impl<'a> IntoIterator for &'a FailureDomain { - type IntoIter = <&'a HashMap<Uppercase, Uppercase> as IntoIterator>::IntoIter; - type Item = <&'a HashMap<Uppercase, Uppercase> as IntoIterator>::Item; - - fn into_iter(self) -> Self::IntoIter { - self.data.iter() - } -} - //////////////////////////////////////////////////////////////////////////////// /// Migration #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] diff --git a/src/traft/rpc/join.rs b/src/traft/rpc/join.rs index 19c6f26a8c..f8b90cbf3b 100644 --- a/src/traft/rpc/join.rs +++ b/src/traft/rpc/join.rs @@ -1,7 +1,8 @@ +use crate::failure_domain::FailureDomain; use crate::instance::{Instance, InstanceId}; use crate::replicaset::ReplicasetId; use crate::storage::ToEntryIter as _; -use crate::traft::{error::Error, node, Address, FailureDomain, PeerAddress, Result}; +use crate::traft::{error::Error, node, Address, PeerAddress, Result}; #[derive(Clone, Debug, ::serde::Serialize, ::serde::Deserialize)] pub struct OkResponse { diff --git a/src/traft/rpc/update_instance.rs b/src/traft/rpc/update_instance.rs index fa66be7d16..ee09a204da 100644 --- a/src/traft/rpc/update_instance.rs +++ b/src/traft/rpc/update_instance.rs @@ -1,7 +1,7 @@ +use crate::failure_domain::FailureDomain; use crate::instance::grade::{CurrentGrade, TargetGradeVariant}; use crate::instance::InstanceId; use crate::tlog; -use crate::traft::FailureDomain; use crate::traft::Result; use crate::traft::{error::Error, node}; diff --git a/src/traft/topology.rs b/src/traft/topology.rs index a5a5b284dc..198a7719d8 100644 --- a/src/traft/topology.rs +++ b/src/traft/topology.rs @@ -1,5 +1,6 @@ use std::collections::{BTreeMap, HashMap, HashSet}; +use crate::failure_domain::FailureDomain; use crate::has_grades; use crate::instance::grade::{ CurrentGrade, CurrentGradeVariant, Grade, TargetGrade, TargetGradeVariant, @@ -10,7 +11,6 @@ use crate::rpc::update_instance; use crate::traft::instance_uuid; use crate::traft::replicaset_uuid; use crate::traft::Address; -use crate::traft::FailureDomain; use crate::traft::RaftId; use crate::util::Uppercase; @@ -243,10 +243,10 @@ mod tests { use super::Topology; + use crate::failure_domain::FailureDomain; use crate::instance::grade::{CurrentGrade, Grade, TargetGrade, TargetGradeVariant}; use crate::traft::instance_uuid; use crate::traft::replicaset_uuid; - use crate::traft::FailureDomain; use crate::traft::Instance; use crate::traft::rpc::update_instance; use pretty_assertions::assert_eq; -- GitLab