stevenschlansker commented on code in PR #18771:
URL: https://github.com/apache/kafka/pull/18771#discussion_r1938120110


##########
streams/src/main/java/org/apache/kafka/streams/state/internals/MeteredKeyValueStore.java:
##########
@@ -156,11 +156,8 @@ private void registerMetrics() {
                 (config, now) -> numOpenIterators.sum());
         StateStoreMetrics.addOldestOpenIteratorGauge(taskId.toString(), 
metricsScope, name(), streamsMetrics,
                 (config, now) -> {
-                    try {
-                        return openIterators.isEmpty() ? null : 
openIterators.first().startTimestamp();
-                    } catch (final NoSuchElementException ignored) {
-                        return null;
-                    }
+                    final Iterator<MeteredIterator> openIteratorsIterator = 
openIterators.iterator();
+                    return openIteratorsIterator.hasNext() ? 
openIteratorsIterator.next().startTimestamp() : null;

Review Comment:
   Thanks for considering this PR @mjsax . I admit I do not have too much 
experience with `ConcurrentSkipListSet` (and the `ConcurrentSkipListMap` 
underlying it), but they promise:
   
   > Iterators and spliterators are weakly consistent.
   
   where weakly consistent is defined:
   
   > Most concurrent Collection implementations (including most Queues) also 
differ from the usual java.util conventions in that their Iterators and 
Spliterators provide weakly consistent rather than fast-fail traversal:
   >    they may proceed concurrently with other operations
   >    they will never throw ConcurrentModificationException
   >    they are guaranteed to traverse elements as they existed upon 
construction exactly once, and may (but are not guaranteed to) reflect any 
modifications subsequent to construction.
   
   I take this to mean that by taking a single `openIterators.iterator()` we 
then get a weakly consistent handle on the structure, and will either observe 
an element or not, but such an iterator should never run into the case where 
`hasNext()` returns `true` but then `next()` throws (which would not be 
"consistent" to me).
   
   I admit the docs stating "they may proceed concurrently with other 
operations" "won't throw CME" isn't 100% clear on this point about the slightly 
different NoSuchElementException.
   
   Assuming my analysis is correct, this is an improvement because the old code 
`isEmpty() + first()` is taking two "weak snapshots" of the data structure that 
are not consistent, but `iterator() { hasNext() + next() }` takes a single weak 
snapshot.
   
   If this isn't sufficiently convincing, I'm fine to drop this PR and move on 
with life :) 



-- 
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: jira-unsubscr...@kafka.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to