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

szetszwo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ratis.git


The following commit(s) were added to refs/heads/master by this push:
     new 51f1e8e90 RATIS-2379. Support returning applied index for ReadIndex 
(#1332)
51f1e8e90 is described below

commit 51f1e8e90a2e289f02f1e18470ceed11fa9c2998
Author: Ivan Andika <[email protected]>
AuthorDate: Sat Jan 10 00:07:58 2026 +0800

    RATIS-2379. Support returning applied index for ReadIndex (#1332)
---
 ratis-docs/src/site/markdown/configurations.md     |  7 +++++++
 .../apache/ratis/server/RaftServerConfigKeys.java  | 15 +++++++++++++++
 .../apache/ratis/server/impl/LeaderStateImpl.java  | 17 +++++++++++------
 .../org/apache/ratis/LinearizableReadTests.java    |  3 +++
 .../TestLinearizableLeaderLeaseReadWithGrpc.java   |  5 +++++
 ...leReadAppliedIndexLeaderLeaseReadWithGrpc.java} | 22 +++-------------------
 ... TestLinearizableReadAppliedIndexWithGrpc.java} | 22 +++-------------------
 .../ratis/grpc/TestLinearizableReadWithGrpc.java   |  5 +++++
 8 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/ratis-docs/src/site/markdown/configurations.md 
b/ratis-docs/src/site/markdown/configurations.md
index 4caf11b30..acd1cb9f9 100644
--- a/ratis-docs/src/site/markdown/configurations.md
+++ b/ratis-docs/src/site/markdown/configurations.md
@@ -218,6 +218,13 @@ if it fails to receive any RPC responses from this peer 
within this specified ti
 | **Type**        | TimeDuration                                               
                    |
 | **Default**     | 60s                                                        
                    |
 
+### Read Index - Configurations related to ReadIndex used in linearizable read 
+
+| **Property**    | `raft.server.read.read-index.applied-index.enabled`        
           |
+|:----------------|:----------------------------------------------------------------------|
+| **Description** | whether applied index (instead of commit index) is used 
for ReadIndex |
+| **Type**        | boolean                                                    
           |
+| **Default**     | false                                                      
           |
 
 
 ### Write - Configurations related to write requests.
diff --git 
a/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java
 
b/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java
index 002286c4c..2538a472a 100644
--- 
a/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java
+++ 
b/ratis-server-api/src/main/java/org/apache/ratis/server/RaftServerConfigKeys.java
@@ -265,6 +265,21 @@ public interface RaftServerConfigKeys {
         setTimeDuration(properties::setTimeDuration, 
WRITE_INDEX_CACHE_EXPIRY_TIME_KEY, expiryTime);
       }
     }
+
+    interface ReadIndex {
+      String PREFIX = Read.PREFIX + ".read-index";
+
+      String APPLIED_INDEX_ENABLED_KEY = PREFIX + ".applied-index.enabled";
+      boolean APPLIED_INDEX_ENABLED_DEFAULT = false;
+      static boolean appliedIndexEnabled(RaftProperties properties) {
+        return getBoolean(properties::getBoolean, APPLIED_INDEX_ENABLED_KEY,
+            APPLIED_INDEX_ENABLED_DEFAULT, getDefaultLog());
+      }
+
+      static void setAppliedIndexEnabled(RaftProperties properties, boolean 
enabled) {
+        setBoolean(properties::setBoolean, APPLIED_INDEX_ENABLED_KEY, enabled);
+      }
+    }
   }
 
   interface Write {
diff --git 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
index 836b15bcd..90d0b76df 100644
--- 
a/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
+++ 
b/ratis-server/src/main/java/org/apache/ratis/server/impl/LeaderStateImpl.java
@@ -353,6 +353,7 @@ class LeaderStateImpl implements LeaderState {
   private final PendingStepDown pendingStepDown;
 
   private final ReadIndexHeartbeats readIndexHeartbeats;
+  private final boolean readIndexAppliedIndexEnabled;
   private final LeaderLease lease;
 
   LeaderStateImpl(RaftServerImpl server) {
@@ -389,6 +390,8 @@ class LeaderStateImpl implements LeaderState {
     } else {
       this.followerMaxGapThreshold = (long) (followerGapRatioMax * 
maxPendingRequests);
     }
+    this.readIndexAppliedIndexEnabled = RaftServerConfigKeys.Read.ReadIndex
+        .appliedIndexEnabled(properties);
 
     final RaftConfigurationImpl conf = state.getRaftConf();
     Collection<RaftPeer> others = conf.getOtherPeers(server.getId());
@@ -1134,21 +1137,23 @@ class LeaderStateImpl implements LeaderState {
   /**
    * Obtain the current readIndex for read only requests. See Raft paper 
section 6.4.
    * 1. Leader makes sure at least one log from current term is committed.
-   * 2. Leader record last committed index as readIndex.
+   * 2. Leader record last committed index or applied index (depending on 
configuration) as readIndex.
    * 3. Leader broadcast heartbeats to followers and waits for 
acknowledgements.
    * 4. If majority respond success, returns readIndex.
    * @return current readIndex.
    */
   CompletableFuture<Long> getReadIndex(Long readAfterWriteConsistentIndex) {
-    final long commitIndex = server.getRaftLog().getLastCommittedIndex();
+    final long index = readIndexAppliedIndexEnabled ?
+        server.getState().getLastAppliedIndex() : 
server.getRaftLog().getLastCommittedIndex();
     final long readIndex;
-    if (readAfterWriteConsistentIndex != null && readAfterWriteConsistentIndex 
> commitIndex) {
+    if (readAfterWriteConsistentIndex != null && readAfterWriteConsistentIndex 
> index) {
       readIndex = readAfterWriteConsistentIndex;
     } else {
-      readIndex = commitIndex;
+      readIndex = index;
     }
-    LOG.debug("readIndex={} (commitIndex={}, 
readAfterWriteConsistentIndex={})",
-        readIndex, commitIndex, readAfterWriteConsistentIndex);
+    LOG.debug("readIndex={} ({}Index={}, readAfterWriteConsistentIndex={})",
+        readIndex, readIndexAppliedIndexEnabled ? "applied" : "commit",
+        index, readAfterWriteConsistentIndex);
 
     // if group contains only one member, fast path
     if (server.getRaftConf().isSingleton()) {
diff --git 
a/ratis-server/src/test/java/org/apache/ratis/LinearizableReadTests.java 
b/ratis-server/src/test/java/org/apache/ratis/LinearizableReadTests.java
index 91bd2f28d..b15ae3067 100644
--- a/ratis-server/src/test/java/org/apache/ratis/LinearizableReadTests.java
+++ b/ratis-server/src/test/java/org/apache/ratis/LinearizableReadTests.java
@@ -60,6 +60,8 @@ public abstract class LinearizableReadTests<CLUSTER extends 
MiniRaftCluster>
 
   public abstract boolean isLeaderLeaseEnabled();
 
+  public abstract boolean readIndexAppliedIndexEnabled();
+
   public abstract void assertRaftProperties(RaftProperties properties);
 
   void runWithNewCluster(CheckedConsumer<CLUSTER, Exception> testCase) throws 
Exception {
@@ -75,6 +77,7 @@ public abstract class LinearizableReadTests<CLUSTER extends 
MiniRaftCluster>
     CounterStateMachine.setProperties(p);
     RaftServerConfigKeys.Read.setOption(p, LINEARIZABLE);
     RaftServerConfigKeys.Read.setLeaderLeaseEnabled(p, isLeaderLeaseEnabled());
+    RaftServerConfigKeys.Read.ReadIndex.setAppliedIndexEnabled(p, 
readIndexAppliedIndexEnabled());
   }
 
   @Test
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
index e45d8f4ff..d637498d7 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
@@ -34,6 +34,11 @@ public class TestLinearizableLeaderLeaseReadWithGrpc
     return true;
   }
 
+  @Override
+  public boolean readIndexAppliedIndexEnabled() {
+    return false;
+  }
+
   @Override
   public void assertRaftProperties(RaftProperties p) {
     assertOption(LINEARIZABLE, p);
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexLeaderLeaseReadWithGrpc.java
similarity index 53%
copy from 
ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
copy to 
ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexLeaderLeaseReadWithGrpc.java
index e45d8f4ff..9bf3e307b 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexLeaderLeaseReadWithGrpc.java
@@ -17,27 +17,11 @@
  */
 package org.apache.ratis.grpc;
 
-import org.apache.ratis.LinearizableReadTests;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.server.RaftServerConfigKeys;
-
-import static org.apache.ratis.ReadOnlyRequestTests.assertOption;
-import static 
org.apache.ratis.server.RaftServerConfigKeys.Read.Option.LINEARIZABLE;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class TestLinearizableLeaderLeaseReadWithGrpc
-  extends LinearizableReadTests<MiniRaftClusterWithGrpc>
-  implements MiniRaftClusterWithGrpc.FactoryGet {
+public class TestLinearizableReadAppliedIndexLeaderLeaseReadWithGrpc
+    extends TestLinearizableLeaderLeaseReadWithGrpc {
 
   @Override
-  public boolean isLeaderLeaseEnabled() {
+  public boolean readIndexAppliedIndexEnabled() {
     return true;
   }
-
-  @Override
-  public void assertRaftProperties(RaftProperties p) {
-    assertOption(LINEARIZABLE, p);
-    assertTrue(RaftServerConfigKeys.Read.leaderLeaseEnabled(p));
-    assertTrue(isLeaderLeaseEnabled());
-  }
 }
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexWithGrpc.java
similarity index 53%
copy from 
ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
copy to 
ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexWithGrpc.java
index e45d8f4ff..c019aac16 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableLeaderLeaseReadWithGrpc.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadAppliedIndexWithGrpc.java
@@ -17,27 +17,11 @@
  */
 package org.apache.ratis.grpc;
 
-import org.apache.ratis.LinearizableReadTests;
-import org.apache.ratis.conf.RaftProperties;
-import org.apache.ratis.server.RaftServerConfigKeys;
-
-import static org.apache.ratis.ReadOnlyRequestTests.assertOption;
-import static 
org.apache.ratis.server.RaftServerConfigKeys.Read.Option.LINEARIZABLE;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class TestLinearizableLeaderLeaseReadWithGrpc
-  extends LinearizableReadTests<MiniRaftClusterWithGrpc>
-  implements MiniRaftClusterWithGrpc.FactoryGet {
+public class TestLinearizableReadAppliedIndexWithGrpc
+  extends TestLinearizableReadWithGrpc {
 
   @Override
-  public boolean isLeaderLeaseEnabled() {
+  public boolean readIndexAppliedIndexEnabled() {
     return true;
   }
-
-  @Override
-  public void assertRaftProperties(RaftProperties p) {
-    assertOption(LINEARIZABLE, p);
-    assertTrue(RaftServerConfigKeys.Read.leaderLeaseEnabled(p));
-    assertTrue(isLeaderLeaseEnabled());
-  }
 }
diff --git 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadWithGrpc.java
 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadWithGrpc.java
index a434fe000..3e8860dd1 100644
--- 
a/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadWithGrpc.java
+++ 
b/ratis-test/src/test/java/org/apache/ratis/grpc/TestLinearizableReadWithGrpc.java
@@ -34,6 +34,11 @@ public class TestLinearizableReadWithGrpc
     return false;
   }
 
+  @Override
+  public boolean readIndexAppliedIndexEnabled() {
+    return false;
+  }
+
   @Override
   public void assertRaftProperties(RaftProperties p) {
     assertOption(LINEARIZABLE, p);

Reply via email to