xiangfu0 commented on code in PR #20024:
URL: https://github.com/apache/pinot/pull/20024#discussion_r4459898158


##########
pinot-core/src/main/java/org/apache/pinot/core/data/manager/realtime/RealtimeSegmentDataManager.java:
##########
@@ -605,6 +627,78 @@ protected boolean consumeLoop()
     return true;
   }
 
+  // TODO Issue 5359 Need to find a way to bump metrics without getting actual 
offset value.
+  private void updateHighestStreamOffsetConsumedGauge() {
+    if (_currentOffset instanceof LongMsgOffset) {
+      // TODO: only LongMsgOffset supplies long offset value.
+      _serverMetrics.setValueOfTableGauge(_clientId, 
ServerGauge.HIGHEST_STREAM_OFFSET_CONSUMED,
+          ((LongMsgOffset) _currentOffset).getOffset());
+    }
+  }
+
+  /// Adopts an empty batch's advanced stream position. Transaction markers 
and aborted records move a stream's
+  /// position without delivering rows, so adoption keeps the position and lag 
current. The skipped offsets are treated
+  /// like a gap between two delivered messages, which needs no further proof 
either: the stream reports a loss
+  /// through `hasDataLoss()`.
+  ///
+  /// @return `true` if `_currentOffset` was advanced
+  private boolean adoptNextBatchOffsetOfEmptyBatch(MessageBatch messageBatch) {
+    StreamPartitionMsgOffset nextBatchOffset = 
messageBatch.getOffsetOfNextBatch();
+    if (nextBatchOffset == null || nextBatchOffset.compareTo(_currentOffset) 
<= 0) {
+      return false;
+    }
+    nextBatchOffset = capAtFinalOffset(messageBatch, nextBatchOffset);
+    if (_segmentLogger.isDebugEnabled()) {
+      _segmentLogger.debug("Empty batch moved the stream position. Advancing 
from {} to {}", _currentOffset,
+          nextBatchOffset);
+    }
+    _currentOffset = nextBatchOffset;
+    return true;
+  }
+
+  /// While catching up to a final offset, caps at it the position of a batch 
that indexes no row (no messages, or
+  /// only filtered ones such as tombstones) when that position lies past the 
final offset. The final offset then lies
+  /// inside an interval no replica indexes rows from, so this replica holds 
exactly the rows below it. A committer can
+  /// stop at such an offset, e.g. one past a Kafka commit marker it skipped 
on an empty poll. A batch reporting loss is
+  /// not capped and keeps the existing overshoot handling.
+  @Nullable
+  private StreamPartitionMsgOffset capAtFinalOffset(MessageBatch messageBatch,
+      @Nullable StreamPartitionMsgOffset nextBatchOffset) {
+    if (nextBatchOffset != null && isCatchingUpToFinalOffset() && 
!messageBatch.hasDataLoss()
+        && nextBatchOffset.compareTo(_finalOffset) > 0) {
+      return _finalOffset;
+    }
+    return nextBatchOffset;
+  }
+
+  /// While catching up to a final offset, stops before a message that starts 
at or past it and settles on the final
+  /// offset. This happens when the final offset is one past offsets the 
stream never delivers, such as a Kafka commit
+  /// marker the committer skipped on an empty poll. The offsets below the 
message are a gap like any other inside a
+  /// data poll, so this replica then holds exactly the rows below the final 
offset.
+  ///
+  /// The existing overshoot handling, which ends in a download, is kept for a 
batch reporting loss, for a message
+  /// straddling the final offset (starting below it), and for a message whose 
offset equals its next offset (inclusive
+  /// offsets such as Kinesis sequence numbers): with those, a message past 
the final offset means this replica's view
+  /// misses one the committer indexed.
+  ///
+  /// @return `true` if consumption must stop before the message
+  private boolean reachedFinalOffsetBeforeMessage(MessageBatch messageBatch, 
StreamPartitionMsgOffset offset,
+      StreamPartitionMsgOffset nextOffset) {
+    if (!isCatchingUpToFinalOffset() || messageBatch.hasDataLoss() || 
_currentOffset.compareTo(_finalOffset) >= 0

Review Comment:
   Non-blocking residual risk: Pulsar's `nextOffset` is a synthetic (ledger, 
entry+1), so it has no legitimate gaps. A follower in CATCHING_UP can only see 
a message at or past the final offset by skipping one, and Pulsar never reports 
loss. The same holds for Kafka read_committed, which never flags loss. Before 
this PR such a follower overshot and downloaded. Now it settles, and KEEP 
retains it without a CRC check (the `settled` case of 
`testKeepRetainsSegmentAtReachedPosition`). It's rare (retention passing a 
follower mid-catch-up), but the committed CRC is in ZK by KEEP time. Verifying 
it after a settle or cap, or limiting settles to streams with real gaps, would 
keep that safety net.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to