From 4aba385d0a28f9a66251b6765650a5eee4dc8ace Mon Sep 17 00:00:00 2001
From: Yaroslav Dynnikov <yaroslav.dynnikov@gmail.com>
Date: Sun, 22 May 2022 00:49:50 +0300
Subject: [PATCH] feature: support instance_uuid

- Generate it in the topology module
- Persist it in `raft_group` space
- Transfer it in `JoinResponse`
- Use it in `box.cfg`

Close https://git.picodata.io/picodata/picodata/picodata/-/issues/50
---
 src/main.rs           |  2 +-
 src/traft/mod.rs      | 16 +++++++++++++++-
 src/traft/storage.rs  |  2 +-
 src/traft/topology.rs |  4 ++++
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index bbea17e08a..e38f354a5e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -472,7 +472,7 @@ fn start_join(args: &args::Run, leader_address: String) {
     let cfg = tarantool::Cfg {
         listen: None,
         read_only: false,
-        // instance_uuid: resp.instance_uuid
+        instance_uuid: Some(resp.peer.instance_uuid.clone()),
         // replicaset_uuid: resp.replicaset_uuid
         replication: resp.box_replication.clone(),
         wal_dir: args.data_dir.clone(),
diff --git a/src/traft/mod.rs b/src/traft/mod.rs
index b1e03c7b73..cc38a84653 100644
--- a/src/traft/mod.rs
+++ b/src/traft/mod.rs
@@ -11,6 +11,7 @@ use ::tarantool::tuple::AsTuple;
 use serde::de::DeserializeOwned;
 use serde::{Deserialize, Serialize};
 use std::convert::TryFrom;
+use uuid::Uuid;
 
 use protobuf::Message as _;
 use protobuf::ProtobufEnum as _;
@@ -69,7 +70,7 @@ pub struct Peer {
     pub voter: bool,
     pub instance_id: String,
     // pub replicaset_id: String,
-    // pub instance_uuid: String,
+    pub instance_uuid: String,
     // pub replicaset_uuid: String,
     /// `0` means it's not committed yet.
     pub commit_index: u64,
@@ -297,3 +298,16 @@ pub struct JoinResponse {
     // pub read_only: bool,
 }
 impl AsTuple for JoinResponse {}
+
+///////////////////////////////////////////////////////////////////////////////
+lazy_static::lazy_static! {
+    static ref NAMESPACE_INSTANCE_UUID: Uuid =
+        Uuid::new_v3(&Uuid::nil(), "INSTANCE_UUID".as_bytes());
+}
+
+/// Generate UUID for an instance from `instance_id` (String).
+/// Use Version-3 (MD5) UUID.
+pub fn instance_uuid(instance_id: &str) -> String {
+    let uuid = Uuid::new_v3(&NAMESPACE_INSTANCE_UUID, instance_id.as_bytes());
+    uuid.hyphenated().to_string()
+}
diff --git a/src/traft/storage.rs b/src/traft/storage.rs
index 88dd995d16..7f2b8e5854 100644
--- a/src/traft/storage.rs
+++ b/src/traft/storage.rs
@@ -76,8 +76,8 @@ impl Storage {
                     {name = 'peer_address', type = 'string', is_nullable = false},
                     {name = 'voter', type = 'boolean', is_nullable = false},
                     {name = 'instance_id', type = 'string', is_nullable = false},
-                    -- {name = 'instance_uuid', type = 'string', is_nullable = false},
                     -- {name = 'replicaset_id', type = 'string', is_nullable = false},
+                    {name = 'instance_uuid', type = 'string', is_nullable = false},
                     -- {name = 'replicaset_uuid', type = 'string', is_nullable = false},
                     {name = 'commit_index', type = 'unsigned', is_nullable = false},
                 }
diff --git a/src/traft/topology.rs b/src/traft/topology.rs
index 49d545094a..12df06d78e 100644
--- a/src/traft/topology.rs
+++ b/src/traft/topology.rs
@@ -1,5 +1,6 @@
 use std::collections::BTreeMap;
 
+use crate::traft::instance_uuid;
 use crate::traft::JoinRequest;
 use crate::traft::Peer;
 use crate::traft::RaftId;
@@ -62,6 +63,7 @@ impl Topology {
                 raft_id,
                 instance_id: req.instance_id.clone(),
                 commit_index: INVALID_INDEX,
+                instance_uuid: instance_uuid(&req.instance_id),
                 peer_address: req.advertise_address.clone(),
                 voter: req.voter,
             };
@@ -81,6 +83,7 @@ impl Topology {
 #[cfg(test)]
 mod tests {
     use super::Topology;
+    use crate::traft::instance_uuid;
     use crate::traft::JoinRequest;
     use crate::traft::Peer;
 
@@ -98,6 +101,7 @@ mod tests {
                     voter: $voter,
                     instance_id: $instance_id.into(),
                     commit_index: raft::INVALID_INDEX,
+                    instance_uuid: instance_uuid($instance_id),
                 }
             ),*]
         };
-- 
GitLab