@@ -176,7 +176,7 @@ public class ReplicaManager {
176176 private final SnapshotContext kvSnapshotContext ;
177177
178178 // remote log manager for remote log storage.
179- private final RemoteLogManager remoteLogManager ;
179+ protected final RemoteLogManager remoteLogManager ;
180180
181181 // for metrics
182182 private final TabletServerMetricGroup serverMetricGroup ;
@@ -217,7 +217,7 @@ public ReplicaManager(
217217 }
218218
219219 @ VisibleForTesting
220- ReplicaManager (
220+ protected ReplicaManager (
221221 Configuration conf ,
222222 Scheduler scheduler ,
223223 LogManager logManager ,
@@ -1111,7 +1111,9 @@ public Map<TableBucket, LogReadResult> readFromLog(
11111111
11121112 FetchLogResultForBucket result ;
11131113 if (replica != null && e instanceof LogOffsetOutOfRangeException ) {
1114- result = handleFetchOutOfRangeException (replica , fetchOffset , e );
1114+ result =
1115+ handleFetchOutOfRangeException (
1116+ replica , fetchOffset , fetchParams .isFromFollower (), e );
11151117 } else {
11161118 result = new FetchLogResultForBucket (tb , ApiError .fromThrowable (e ));
11171119 }
@@ -1123,7 +1125,7 @@ public Map<TableBucket, LogReadResult> readFromLog(
11231125 }
11241126
11251127 private FetchLogResultForBucket handleFetchOutOfRangeException (
1126- Replica replica , long fetchOffset , Exception e ) {
1128+ Replica replica , long fetchOffset , boolean isFromFollower , Exception e ) {
11271129 TableBucket tb = replica .getTableBucket ();
11281130 if (fetchOffset == FetchParams .FETCH_FROM_EARLIEST_OFFSET ) {
11291131 fetchOffset = replica .getLogStartOffset ();
@@ -1141,7 +1143,8 @@ private FetchLogResultForBucket handleFetchOutOfRangeException(
11411143 // of RemoteLogSegment. For client fetcher, it will fetch the log from remote in client.
11421144 // For follower, it can update its local metadata to adjust the next fetch offset.
11431145 else if (canFetchFromRemoteLog (replica , fetchOffset )) {
1144- RemoteLogFetchInfo remoteLogFetchInfo = fetchLogFromRemote (replica , fetchOffset );
1146+ RemoteLogFetchInfo remoteLogFetchInfo =
1147+ fetchLogFromRemote (replica , fetchOffset , isFromFollower );
11451148 if (remoteLogFetchInfo != null ) {
11461149 return new FetchLogResultForBucket (
11471150 tb , remoteLogFetchInfo , replica .getLogHighWatermark ());
@@ -1167,13 +1170,20 @@ private boolean canFetchFromRemoteLog(Replica replica, long fetchOffset) {
11671170 return replica .getLogTablet ().canFetchFromRemoteLog (fetchOffset );
11681171 }
11691172
1170- private @ Nullable RemoteLogFetchInfo fetchLogFromRemote (Replica replica , long fetchOffset ) {
1173+ private @ Nullable RemoteLogFetchInfo fetchLogFromRemote (
1174+ Replica replica , long fetchOffset , boolean isFromFollower ) {
11711175 List <RemoteLogSegment > remoteLogSegmentList =
11721176 remoteLogManager .relevantRemoteLogSegments (replica .getTableBucket (), fetchOffset );
11731177 if (!remoteLogSegmentList .isEmpty ()) {
1174- int firstStartPos =
1175- remoteLogManager .lookupPositionForOffset (
1176- remoteLogSegmentList .get (0 ), fetchOffset );
1178+ // follower does not require firstStartPos, so we do not look up this value.
1179+ // On one hand, this reduces query overhead, and on the other hand,
1180+ // it helps prevent unexpected issues caused by corrupted index files.
1181+ int firstStartPos = -1 ;
1182+ if (!isFromFollower ) {
1183+ firstStartPos =
1184+ remoteLogManager .lookupPositionForOffset (
1185+ remoteLogSegmentList .get (0 ), fetchOffset );
1186+ }
11771187 PhysicalTablePath physicalTablePath = replica .getPhysicalTablePath ();
11781188 FsPath remoteLogTabletDir =
11791189 FlussPaths .remoteLogTabletDir (
0 commit comments