Skip to content

Do not return documents before the seek range after a unique rebuild - #3974

Open
SethSmucker wants to merge 3 commits into
integrationfrom
a4qs/unique-rebuild-range
Open

SethSmucker wants to merge 3 commits into
integrationfrom
a4qs/unique-rebuild-range

Conversation

@SethSmucker

@SethSmucker SethSmucker commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #3973

In QueryIterator.seek, after applying the unique transform, drop any entry that sorts before the seek range start. After a teardown the unique transform reloads documents it already returned, and nothing before the range start belongs in the results anyway. This covers subclasses such as AncestorQueryIterator, which turn the teardown range into an inclusive one before calling QueryIterator.seek. Yield resumes are left alone: their start key is the yield marker, and the documents before it have not been returned yet.

QueryIteratorIT.most_recent_unique_after_teardown covers it: TestLookupTask.lookupWithTeardown rebuilds the iterator after every result and seeks again just past the last key, as a tablet server does after a teardown, and fails if a rebuilt iterator returns a key that does not follow it. Without this change the rebuilt iterator returns the same document again; with it the test passes. It drives QueryIterator directly, so it does not depend on InMemoryScanner.

Tested on integration (JDK 11) and on accumulo4-2026-quickstart: the full query-core unit suite passes on integration (7,373 tests), including QueryIteratorIT and its four subclasses (Ancestor, TLD and both WaitWindow ITs) and UniqueTest. On the a4 branch, which builds in-memory-accumulo from source, this also stops UniqueTest.testMostRecentUniquenessWithIterator from hanging.

// returned and sort before the seek range. A tablet server passes such keys straight to the client, so drop them here. A yield resume
// is left alone: its start key is the yield marker, and documents before it have not been returned yet.
final Range seekRange = range;
pipelineDocuments = Iterators.filter(pipelineDocuments, entry -> !seekRange.beforeStartKey(entry.getKey()));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It's a known bug that the most recent unique function can return keys out of order. For a change as significant as this paired with the commit message comment about a hanging test, I would expect to see at least one example of a test that fails without this change going from red to green.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added most_recent_unique_after_teardown in QueryIteratorIT, checking for this explicit case

@lbschanno

Copy link
Copy Markdown
Collaborator

Should this bugfix get pointed against the integration branch instead since it also applies there?

@SethSmucker SethSmucker added the Accumulo 4 Work associated with getting Datawave ready for Accumulo 4 label Oct 8, 2026
When a scan is torn down and rebuilt, the most-recent unique transform reloads
the documents it persisted before the rebuild and hands them back from the
start, including ones already returned. InMemoryScanner used to drop those keys
with a range filter, which #3803 removed because a tablet server does not. This
filters them in QueryIterator instead. Yield resumes are left alone, since their
start key is the yield marker and the documents before it are still owed.
Add TestLookupTask.lookupWithTeardown, which rebuilds the iterator after every
result and seeks it again just after the last key, as a tablet server does
after a teardown, and fails if a rebuilt iterator returns a key that does not
follow it. QueryIteratorIT.most_recent_unique_after_teardown runs the
most_recent_unique query through it: without the QueryIterator change the
rebuilt iterator returns the same document again, with it the test passes.
It drives QueryIterator directly, so it does not depend on InMemoryScanner.
@SethSmucker
SethSmucker changed the base branch from accumulo4-2026-quickstart to integration October 8, 2026 16:44
@SethSmucker
SethSmucker force-pushed the a4qs/unique-rebuild-range branch from 664ec4a to 17f394e Compare October 8, 2026 16:44
@apmoriarty

Copy link
Copy Markdown
Collaborator

Should this bugfix get pointed against the integration branch instead since it also applies there?

Yes, it should. Thank you @SethSmucker for targeting integration

@lbschanno lbschanno removed the Accumulo 4 Work associated with getting Datawave ready for Accumulo 4 label Oct 9, 2026
AncestorQueryIterator turns a teardown's exclusive range into an inclusive one
starting just past the returned document before calling QueryIterator.seek, so
the filter never applied and AncestorQueryIteratorIT, which inherits
most_recent_unique_after_teardown, still saw the document returned again.
Apply the filter whenever the seek start is not a yield marker; nothing before
the range start belongs in the results either way.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UniqueTest hangs on the Accumulo 4 branch: most-recent unique returns documents before the seek range after a rebuild

3 participants