Skip to content

API, Core: Support onKeep/onSkip callback for FilterIterator#17118

Open
dramaticlly wants to merge 2 commits into
apache:mainfrom
dramaticlly:mtered-iterables
Open

API, Core: Support onKeep/onSkip callback for FilterIterator#17118
dramaticlly wants to merge 2 commits into
apache:mainfrom
dramaticlly:mtered-iterables

Conversation

@dramaticlly

Copy link
Copy Markdown
Contributor

What

Add a new filter overload that invokes a Consumer on each accepted and rejected element, so callers can attribute both kept and skipped entries to metrics in a single pass.

Why

This help provide a path for hetergeneous entry of TrackedFile in v4, where a given entry can carry contentType of DATA, EQUALITY_DELETES, DATA_MANIFEST, or DELETE_MANIFEST within a single root manifest. Callback is better suited than a dedicated counter to allow more flexibility. Plus, import org.apache.iceberg.metrics.Counter in org.apache.iceberg.io. CloseableIterable is not ideal for a general purpose iteration utility.

Existing caller

Migrate the manifest-level scan pipelines in DeleteFileIndex, PositionDeletesTable, and ManifestGroup where each previously chained a skip-counting filter with a scan-counting count call. Now replaced with a single filter call with both onKeep and onSkip callback. File-level filters in ManifestReader and ManifestGroup remain on the counter-based overload since ScanMetrics only exposes a skipped counter at that layer.

Add a new filter overload that invokes a Consumer on each accepted and
rejected element, so callers can attribute both survivors and skipped
entries to metrics in a single pass. The counter-based filter and count
helpers delegate to this new primitive.

Migrate the manifest-level scan pipelines in DeleteFileIndex,
PositionDeletesTable, and ManifestGroup — each previously chained a
skip-counting filter with a scan-counting count call — to a single
filter call with both onKeep and onSkip observers. File-level filters
in ManifestReader and ManifestGroup remain on the counter-based
overload since ScanMetrics only exposes a skipped counter at that layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dramaticlly

Copy link
Copy Markdown
Contributor Author

FYI @stevenzwu @anoopj @nastra if you want to take a look.

iterable.close();
}
};
return filter(iterable, item -> true, item -> counter.increment(), item -> {});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

count now delegates to the FilterIterator-based filter, which increments during hasNext()/advance() rather than on next() like CloseableIterator.count. The javadoc still says the counter is incremented on each Iterator#next() call, so peeking via hasNext() without a following next() over-counts. Update the javadoc, or keep count on CloseableIterator.count.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @wombatu-kun for the review. I updated to change FilterIterator directly so that we keep exactly once semantics for skip on hasNext() and kept on next(), same as before.

Move the keep/skip observation into FilterIterator via overridable
onKeep(T) and onSkip(T) hook methods with no-op defaults. onSkip fires
inside advance() right after shouldKeep returns false, onKeep fires
inside next() right before the accepted element is delivered — matching
the historical timing of the counter-based helpers.

This aligns with what Ryan Blue proposed on the original PR (apache#5268 review
comment r929192438): put counter support directly in FilterIterator
rather than layering it via predicates or wrapping iterators. It also
lets CloseableIterable.filter drop its outer next()-intercepting wrapper.
this.nextReady = true;
return true;
}
onSkip(next);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rdblue I think this align with your previous suggestion in #5268 (comment). A custom callback enable different counter for v4 heterogenous entry of trackedFile

@dramaticlly dramaticlly changed the title API, Core: Add CloseableIterable.filter with keep/skip callback for hetergeneous element API, Core: Support onKeep/onSkip callback for FilterIterator Jul 7, 2026
@stevenzwu

Copy link
Copy Markdown
Contributor

If this is mainly for v4, maybe we should wait until the basic plumbing of write and read get in first. Then we will have a better idea on how other pieces (like this) fit in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants