fix(indexer): price-window has_more counts in-band rows only (#270) #735

Merged
Brouie merged 1 commit from qa/270-price-window-has-more into main 2026-06-02 14:19:58 +00:00
Brouie commented 2026-06-02 13:28:18 +00:00 (Migrated from gitlab.com)

Fixes #270. fetch_limit_book_price_window reported has_more: true whenever the FIFO chain continued past the band, even when the whole in-band slice fit one page — because it used has_more = current.is_some(), the same rule as full-book pagination. For a price window has_more must mean "another page may return more in-band rows for this band", not "the book continues outside the band".

Fix (price window only — fetch_limit_book_page untouched)

  • past_band exit → has_more = false (in-band region is exhausted; the book is price-ordered). Zero extra LCD query — just the boolean flips.
  • chain end → has_more = false.
  • page full → peek the one successor and set has_more = true only if it classifies in-band. The peek costs one fetch_limit_order, gated on the per-page budget (LIMIT_BOOK_LCD_QUERY_BUDGET = 101): if the budget is already spent, has_more stays true — a bounded over-report (next page returns the remaining in-band rows or one empty past-band page, then false), mirroring the merged-stream has_more = current.is_some() || budget_exhausted pattern.

next_after_order_id stays the last returned in-band id; orders[], band inclusivity, bid/ask rules, the budget constant, and LCD query counting are all unchanged.

Side effect (documented in the fn doc-comment): a broken/wrong-side immediate successor now surfaces its corrupt-book 400 one page earlier for the price-window route — the same integrity checks the walk loop already applies; a healthy book never hits it.

Tests (api_limit_book_insert_hints)

  • New mock books: below-band bid tail (…→4@1.0→5@0.5), above-band ask tail (…→13@1.5→14@2.0).
  • price_window_has_more_excludes_out_of_band_tail — bid and ask through both exit paths: past_band tail, cap-at-floor, cap<depth multi-page (page-1 has_more + cursor, page-2 remainder then false), empty band. Includes LCD query-count asserts: past_band adds 0 peek queries; a page-full in-band peek adds exactly 1.
  • price_window_has_more_budget_exhaustion_over_reports — deep all-in-band book, limit=100: page fills as the budget is spent → has_more=true over-report, cursor = last in-band id, 101 queries (peek suppressed, no 102nd LCD call).

Verification

  • cargo test -p cl8y-dex-indexer --test api_limit_book_insert_hints: 5 passed.
  • Regression: api_limit_book_lcd_mock 5, api_limit_book_deep 1 — still green (incl. the original [1.5,1.0] window case).
  • cargo clippy -p cl8y-dex-indexer --all-targets: clean on touched files (remaining lints are pre-existing toolchain drift in other modules).
  • No wasm/contract change.
  • Diff went through an adversarial multi-agent review (correctness/budget/test-coverage/regression lenses); the coverage gaps it surfaced (ask peek path, budget over-report branch, query-count guardrail) are now covered by the tests above.

docs/integrators.md documents the price-window has_more semantics.

Closes #270 once merged.

Fixes #270. `fetch_limit_book_price_window` reported `has_more: true` whenever the FIFO chain continued past the band, even when the whole in-band slice fit one page — because it used `has_more = current.is_some()`, the same rule as full-book pagination. For a price window `has_more` must mean "another page may return more **in-band** rows for this band", not "the book continues outside the band". ### Fix (price window only — `fetch_limit_book_page` untouched) - **past_band** exit → `has_more = false` (in-band region is exhausted; the book is price-ordered). Zero extra LCD query — just the boolean flips. - **chain end** → `has_more = false`. - **page full** → peek the one successor and set `has_more = true` only if it classifies in-band. The peek costs one `fetch_limit_order`, gated on the per-page budget (`LIMIT_BOOK_LCD_QUERY_BUDGET = 101`): if the budget is already spent, `has_more` stays `true` — a **bounded** over-report (next page returns the remaining in-band rows or one empty past-band page, then `false`), mirroring the merged-stream `has_more = current.is_some() || budget_exhausted` pattern. `next_after_order_id` stays the last returned in-band id; `orders[]`, band inclusivity, bid/ask rules, the budget constant, and LCD query counting are all unchanged. Side effect (documented in the fn doc-comment): a broken/wrong-side immediate successor now surfaces its corrupt-book 400 one page earlier for the price-window route — the same integrity checks the walk loop already applies; a healthy book never hits it. ### Tests (`api_limit_book_insert_hints`) - New mock books: below-band bid tail (`…→4@1.0→5@0.5`), above-band ask tail (`…→13@1.5→14@2.0`). - `price_window_has_more_excludes_out_of_band_tail` — bid **and** ask through **both** exit paths: past_band tail, cap-at-floor, cap<depth multi-page (page-1 `has_more` + cursor, page-2 remainder then `false`), empty band. Includes **LCD query-count asserts**: past_band adds **0** peek queries; a page-full in-band peek adds **exactly 1**. - `price_window_has_more_budget_exhaustion_over_reports` — deep all-in-band book, `limit=100`: page fills as the budget is spent → `has_more=true` over-report, cursor = last in-band id, **101** queries (peek suppressed, no 102nd LCD call). ### Verification - `cargo test -p cl8y-dex-indexer --test api_limit_book_insert_hints`: 5 passed. - Regression: `api_limit_book_lcd_mock` 5, `api_limit_book_deep` 1 — still green (incl. the original `[1.5,1.0]` window case). - `cargo clippy -p cl8y-dex-indexer --all-targets`: clean on touched files (remaining lints are pre-existing toolchain drift in other modules). - No wasm/contract change. - Diff went through an adversarial multi-agent review (correctness/budget/test-coverage/regression lenses); the coverage gaps it surfaced (ask peek path, budget over-report branch, query-count guardrail) are now covered by the tests above. `docs/integrators.md` documents the price-window `has_more` semantics. Closes #270 once merged.
Brouie commented 2026-06-02 13:29:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #270

mentioned in issue #270
PlasticDigits commented 2026-06-02 14:19:58 +00:00 (Migrated from gitlab.com)

mentioned in commit d8ed85583e

mentioned in commit d8ed85583e9b37ef7889c04d40158aa83d979778
PlasticDigits (Migrated from gitlab.com) merged commit d8ed85583e into main 2026-06-02 14:19:59 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic!735
No description provided.