From b4dd9b852fe02266f6a530643ee93b6552190dc0 Mon Sep 17 00:00:00 2001
From: Georgy Moshkin <gmoshkin@picodata.io>
Date: Mon, 21 Aug 2023 15:07:16 +0300
Subject: [PATCH] fix: tests broke after rebasing on top of update instance
 request changes

---
 src/lib.rs                 | 25 +++++++++++++++++++++++++
 src/rpc/update_instance.rs | 16 +++++++++++++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index a7e8fc0c04..b0ffd4c700 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -704,6 +704,31 @@ fn postjoin(args: &args::Run, storage: Clusterwide, raft_storage: RaftSpaceAcces
         }
     }
 
+    // Wait for target grade to change to Online, so that sentinel doesn't send
+    // a redundant unpdate instance request.
+    // Otherwise incarnations grow by 2 every time.
+    let timeout = Duration::from_secs(10);
+    let deadline = fiber::clock().saturating_add(timeout);
+    loop {
+        let instance = storage
+            .instances
+            .get(&raft_id)
+            .expect("instance must be persisted at the time of postjoin");
+        if has_grades!(instance, * -> Online) {
+            tlog!(Info, "self-activated successfully");
+            break;
+        }
+        if fiber::clock() > deadline {
+            tlog!(
+                Warning,
+                "didn't receive confirmation of self activation in time"
+            );
+            break;
+        }
+        let index = node.get_index();
+        _ = node.wait_index(index + 1, deadline.duration_since(fiber::clock()));
+    }
+
     node.sentinel_loop.on_self_activate();
 }
 
diff --git a/src/rpc/update_instance.rs b/src/rpc/update_instance.rs
index 66e6d18644..f7eff464f3 100644
--- a/src/rpc/update_instance.rs
+++ b/src/rpc/update_instance.rs
@@ -106,9 +106,19 @@ pub fn handle_update_instance_request_and_wait(req: Request, timeout: Duration)
 
     let deadline = fiber::clock().saturating_add(timeout);
     loop {
-        let mut instance = storage.instances.get(&req.instance_id)?;
-        update_instance(&mut instance, &req, storage).map_err(raft::Error::ConfChangeError)?;
-        let dml = Dml::replace(ClusterwideSpaceId::Instance, &instance)
+        let old_instance = storage.instances.get(&req.instance_id)?;
+        let mut new_instance = old_instance.clone();
+        update_instance(&mut new_instance, &req, storage).map_err(raft::Error::ConfChangeError)?;
+        if old_instance == new_instance {
+            // No point in proposing an operation which doesn't change anything.
+            // Note: if the request tried setting target grade Online while it
+            // was already Online the incarnation will be increased and so
+            // old_instance will be different from new_instance and this is the
+            // intended behaviour.
+            return Ok(());
+        }
+
+        let dml = Dml::replace(ClusterwideSpaceId::Instance, &new_instance)
             .expect("encoding should not fail");
 
         let ranges = vec![
-- 
GitLab