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