Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAK-11284: Greedy Reuse of cluster IDs may lead to synchronous LastRe… #1877

Draft
wants to merge 6 commits into
base: trunk
Choose a base branch
from

Conversation

mbaedke
Copy link
Contributor

@mbaedke mbaedke commented Nov 26, 2024

…vRecovery executions slowing down startup

Introduced the system variable oak.syncRecoveryTimeout to limit the duration of a self recovery at startup.

…vRecovery executions slowing down startup

Introduced the system variable oak.syncRecoveryTimeout to limit the duration of a self recovery at startup.
@mbaedke mbaedke marked this pull request as draft November 26, 2024 14:35
@mbaedke mbaedke requested a review from reschke November 26, 2024 14:35
…vRecovery executions slowing down startup

Changed property name for better code readability.
Copy link

sonarcloud bot commented Nov 27, 2024

@reschke
Copy link
Contributor

reschke commented Dec 3, 2024

Minor changes:

  1. simplify sys property access
  2. use custom clock used by LRA
  3. log in ISO format and only if deadline changed
  4. add logging for the case above
diff --git a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
index 0418751982..caa88e1b9a 100644
--- a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
+++ b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/LastRevRecoveryAgent.java
@@ -29,11 +29,11 @@ import static org.apache.jackrabbit.oak.plugins.document.util.Utils.PROPERTY_OR_
 import static org.apache.jackrabbit.oak.plugins.document.util.Utils.isCommitted;
 import static org.apache.jackrabbit.oak.plugins.document.util.Utils.resolveCommitRevision;

-import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -82,7 +82,8 @@ public class LastRevRecoveryAgent {

     private final Consumer<Integer> afterRecovery;

-    private static final SystemPropertySupplier<Long> SYNC_RECOVERY_TIMEOUT_MILLIS = SystemPropertySupplier.create("oak.syncRecoveryTimeoutMillis", Long.MAX_VALUE);
+    private static final long SYNC_RECOVERY_TIMEOUT_MILLIS =
+            SystemPropertySupplier.create("oak.syncRecoveryTimeoutMillis", Long.MAX_VALUE).get();

     private static final long LOGINTERVALMS = TimeUnit.MINUTES.toMillis(1);

@@ -272,11 +273,19 @@ public class LastRevRecoveryAgent {
             ClusterNodeInfoDocument nodeInfo = missingLastRevUtil.getClusterNodeInfo(clusterId);
             if (nodeInfo != null && nodeInfo.isActive()) {
                 deadline = nodeInfo.getLeaseEndTime() - ClusterNodeInfo.DEFAULT_LEASE_FAILURE_MARGIN_MILLIS;
+                log.info("Deadline for synchronous recovery is {}.",
+                        LocalDateTime.ofEpochSecond(deadline, 0, ZoneOffset.UTC));
             }
-            long now = System.currentTimeMillis();
-            if (Long.MAX_VALUE - SYNC_RECOVERY_TIMEOUT_MILLIS.get() > now) {
-                deadline = Math.min(deadline, now + SYNC_RECOVERY_TIMEOUT_MILLIS.get());
-                log.info("Adjusted deadline for synchronous recovery. New deadline is {}", SimpleDateFormat.getDateTimeInstance().format(new Date(deadline)));
+            long now = revisionContext.getClock().millis();
+            // defensive: make sure we don't get an overflow below
+            if (Long.MAX_VALUE - SYNC_RECOVERY_TIMEOUT_MILLIS > now) {
+                long prevDeadline = deadline;
+                deadline = Math.min(deadline, now + SYNC_RECOVERY_TIMEOUT_MILLIS);
+                if (deadline != prevDeadline) {
+                    log.info("Adjusted deadline for synchronous recovery from {} to {}.",
+                            LocalDateTime.ofEpochSecond(prevDeadline, 0, ZoneOffset.UTC),
+                            LocalDateTime.ofEpochSecond(deadline, 0, ZoneOffset.UTC));
+                }
             }
         }

@stefan-egli
Copy link
Contributor

haven't thought much about impact of this but just wanted to state (the obvious) that we'd need to be careful to not cause higher cluster IDs to be used than previously. The more cluster IDs that have ever been used in a deployment, the higher some cost (RevisionVector getting larger, some operations iterating over all (ever existing) cluster IDs)

@reschke
Copy link
Contributor

reschke commented Dec 3, 2024

@stefan-egli - that sort of is the point. It allows the user to trade conservative use of clusterIds with shorter startup time (which, in our case, was seen at around 10min when the server had been crashed and stayed off for a longer period of time)

@stefan-egli
Copy link
Contributor

right, so this needs to be rolled out with care

@reschke
Copy link
Contributor

reschke commented Dec 3, 2024

well, it's opt-in...

@mbaedke mbaedke requested a review from reschke December 4, 2024 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants