This is an automated email from the ASF dual-hosted git repository.

stefanegli pushed a commit to branch OAK-10281
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 1d3c1f5fee7751b0c53320c5d8bbeb68d333fdf8
Author: Stefan Egli <[email protected]>
AuthorDate: Mon Jan 22 17:39:38 2024 +0100

    OAK-10281 : oak.documentMK.recoveryDelaySecs introduced, default 0
---
 .../oak/plugins/document/ClusterNodeInfo.java      | 23 +++++++++++++++++++
 .../plugins/document/ClusterNodeInfoDocument.java  |  2 +-
 .../oak/plugins/document/ClusterNodeInfoTest.java  | 26 ++++++++++++++++++++++
 3 files changed, 50 insertions(+), 1 deletion(-)

diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
index d53e1822f9..3090732d91 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
@@ -229,6 +229,15 @@ public class ClusterNodeInfo {
     /** OAK-3399 : max number of times we're doing a 1sec retry loop just 
before declaring lease failure **/
     private static final int MAX_RETRY_SLEEPS_BEFORE_LEASE_FAILURE = 5;
 
+    /** OAK-10281 : seconds to delay a recovery after a lease timeout */
+    private static final int DEFAULT_RECOVERY_DELAY_SECS = 
SystemPropertySupplier.create("oak.documentMK.recoveryDelaySecs", 0)
+            .loggingTo(LOG).validateWith(value -> value >= 0)
+            .formatSetMessage((name, value) -> String.format("recovery delay 
set to (secs): %ss (using system property %s)", name, value)).get();
+    private static final long DEFAULT_RECOVERY_DELAY_MILLIS = 1000L * 
(long)DEFAULT_RECOVERY_DELAY_SECS;
+
+    // kept non-final for testing purpose
+    static long recoveryDelayMillis = DEFAULT_RECOVERY_DELAY_MILLIS;
+
     /**
      * The Oak version.
      */
@@ -1180,6 +1189,20 @@ public class ClusterNodeInfo {
         clock = Clock.SIMPLE;
     }
 
+    static long getRecoveryDelayMillis() {
+        return recoveryDelayMillis;
+    }
+
+    /** <b>only used for testing</b> **/
+    static void setRecoveryDelayMillis(long recoveryDelayMillis) {
+        ClusterNodeInfo.recoveryDelayMillis = recoveryDelayMillis;
+    }
+
+    /** <b>only used for testing</b> **/
+    static void resetRecoveryDelayMillisToDefault() {
+        recoveryDelayMillis = DEFAULT_RECOVERY_DELAY_MILLIS;
+    }
+
     private static long getProcessId() {
         try {
             String name = ManagementFactory.getRuntimeMXBean().getName();
diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
index aa7d5ead06..adfb83161d 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
@@ -108,7 +108,7 @@ public class ClusterNodeInfoDocument extends Document {
      */
     public boolean isRecoveryNeeded(long currentTimeMillis) {
         return isActive() &&
-                (currentTimeMillis > getLeaseEndTime() ||
+                (currentTimeMillis - getLeaseEndTime() > 
ClusterNodeInfo.getRecoveryDelayMillis() ||
                         isBeingRecovered());
     }
 
diff --git 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
index 5622a3b6ca..7d26d3519a 100644
--- 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
+++ 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoTest.java
@@ -78,6 +78,7 @@ public class ClusterNodeInfoTest {
     @After
     public void after() {
         ClusterNodeInfo.resetClockToDefault();
+        ClusterNodeInfo.resetRecoveryDelayMillisToDefault();
     }
 
     @Test
@@ -708,6 +709,31 @@ public class ClusterNodeInfoTest {
         assertFalse(handler.isLeaseFailure());
     }
 
+    @Test
+    public void recoveryNeededNoDelay() throws Exception {
+        ClusterNodeInfo info = newClusterNodeInfo(1);
+        String key = String.valueOf(info.getId());
+        ClusterNodeInfoDocument doc = store.find(Collection.CLUSTER_NODES, 
key);
+        assertFalse(doc.isRecoveryNeeded(clock.getTime()));
+        clock.waitUntil(info.getLeaseEndTime() + 1);
+        assertTrue(doc.isRecoveryNeeded(clock.getTime()));
+    }
+
+    @Test
+    public void recoveryNeededWithDelay() throws Exception {
+        ClusterNodeInfo.setRecoveryDelayMillis(60000);
+        ClusterNodeInfo info = newClusterNodeInfo(1);
+        String key = String.valueOf(info.getId());
+        ClusterNodeInfoDocument doc = store.find(Collection.CLUSTER_NODES, 
key);
+        assertFalse(doc.isRecoveryNeeded(clock.getTime()));
+        clock.waitUntil(info.getLeaseEndTime() + 59999);
+        assertFalse(doc.isRecoveryNeeded(clock.getTime()));
+        clock.waitUntil(info.getLeaseEndTime() + 1);
+        assertFalse(doc.isRecoveryNeeded(clock.getTime()));
+        clock.waitUntil(info.getLeaseEndTime() + 1);
+        assertTrue(doc.isRecoveryNeeded(clock.getTime()));
+    }
+
     private void assertLeaseFailure() throws Exception {
         for (int i = 0; i < 100; i++) {
             if (handler.isLeaseFailure()) {

Reply via email to