Skip to content

fix(core): don't re-emit the batch-boundary record when paging with a limit that is a multiple of 500 - #3207

Open
SebastianGruza wants to merge 1 commit into
apache:masterfrom
SebastianGruza:fix/paging-batch-boundary
Open

SebastianGruza wants to merge 1 commit into
apache:masterfrom
SebastianGruza:fix/paging-batch-boundary

Conversation

@SebastianGruza

Copy link
Copy Markdown

Purpose of the PR

Following the page token with a limit that is a multiple of 500 returns the last element of page k again as the first element of page k+1, one duplicate per page boundary. It affects every query whose result is one backend entry with more than 500 columns: the edges of one owner vertex (no condition, sort-key prefix or range, either direction) and vertex queries by label through the label index. RocksDB and HStore alike, because it is server code; secondary/range/search index queries are not affected (each index key is its own entry).

Main Changes

BinaryEntryIterator.fetch() appended a record to the current entry and only then checked whether that entry had reached INLINE_BATCH_SIZE (500) to break. The next page restarts inclusively from results.position(), which at that point already points at the appended record, so a page ending exactly at a batch boundary re-emits it. The change starts a new entry with the record once the current entry already holds a full batch, so position() never points at a record that has been emitted. No other behaviour changes; limits that are not a multiple of 500 take exactly the same path as before.

Verifying these changes

  • Trivial rework / code cleanup without any test coverage.
  • Already covered by existing tests.
  • Need tests and can be verified as follows:
    • EdgeCoreTest.testQueryOutEdgesOfVertexInPagingAtBatchBoundary: 1 200 edges of one vertex, paged with limit 400 / 500 / 600 / 1000; asserts the total count and the number of distinct ids for each limit. Red on master for 500 and 1000 (1 202 and 1 201 results), green with the change.
    • EdgeCoreTest and VertexCoreTest on rocksdb and memory (core-test profile): all green.
    • Same result set on a 3-store HStore cluster and a RocksDB oracle for the paged shapes of issue [Bug] Paging returns the page-boundary record twice when limit is a multiple of 500 (BinaryEntryIterator; RocksDB and HStore) #3191 (n=1214 uniq=1212 before, 1212/1212 after), measured with the black-box suite linked in the issue.

Does this PR potentially affect the following parts?

  • Dependencies
  • Modify configurations
  • The public API
  • Nope

Documentation Status

  • Doc - No Need

… limit that is a multiple of 500

BinaryEntryIterator appends a record to the current entry, then breaks
when that entry has reached INLINE_BATCH_SIZE (500). The next page restarts
inclusively from results.position(), which already points at that record,
so a page limit ending exactly at a batch boundary (500, 1000, ...) returned
the last element of page k again as the first element of page k+1. Start a
new entry with the record instead of appending it once the current entry
holds a full batch.

Affects every query whose result is one backend entry with more than 500
columns: the edges of one owner vertex and label-index vertex queries, on
RocksDB and HStore alike (server code).

close apache#3191

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
SebastianGruza added a commit to SebastianGruza/hugegraph-validation that referenced this pull request Sep 14, 2026
@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 33.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 37.86%. Comparing base (60c8803) to head (2fd46a6).

Files with missing lines Patch % Lines
...egraph/backend/serializer/BinaryEntryIterator.java 33.33% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master    #3207   +/-   ##
=========================================
  Coverage     37.86%   37.86%           
- Complexity     6586     6587    +1     
=========================================
  Files           800      800           
  Lines         68985    68987    +2     
  Branches       9172     9173    +1     
=========================================
+ Hits          26120    26123    +3     
- Misses        39796    39797    +1     
+ Partials       3069     3067    -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bitflicker64 bitflicker64 left a comment

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.

Blocking: no. Summary: At 2fd46a6 the fix is correct. On the base code the 500-column check ran after the record was merged, while position() still pointed at that record, so a page ending on the batch boundary re-emitted it. Stashing the record as a fresh next entry leaves position() on an unemitted record, the same way the existing new-entry branch already works. Every merger builds a fresh entry for merger.apply(null, elem) (RocksDB, HStore and HBase, OLAP variants included), unlimited scans still yield 500-column entries, and limits that are not multiples of 500 take the same path as before. Evidence: static review of the full diff against 60c8803 and the code around it, including BackendEntryIterator limit/offset handling, Query.reachLimit, BinaryBackendEntry.columns(), and the position() implementations in RocksDBStdSessions (hasNext() sets the position before next() returns the key), HbaseSessions.RowIterator and HstoreSessionsImpl. In CI at this head, CoreTestSuite passes on rocksdb (815 run, 0 failures) and hbase (815 run, 0 failures); both support paging, so the new test runs there. The only non-green check is codecov/patch. One gap worth a follow-up: the test covers only edges of one vertex, not the label-index vertex query the description also mentions.

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.

[Bug] Paging returns the page-boundary record twice when limit is a multiple of 500 (BinaryEntryIterator; RocksDB and HStore)

2 participants