Skip to content

Harden fractional index generation - #29

Merged
SegaraRai merged 2 commits into
mainfrom
codex/fix-fractional-indexing-audit
Jul 31, 2026
Merged

Harden fractional index generation#29
SegaraRai merged 2 commits into
mainfrom
codex/fix-fractional-indexing-audit

Conversation

@SegaraRai

@SegaraRai SegaraRai commented Jul 31, 2026

Copy link
Copy Markdown
Owner

What changed

  • keep conflict-retry candidates strictly ordered inside their requested bounds
  • make retry selection logarithmic in the skip count
  • reject oversized inputs and generation counts before expensive allocation or midpoint work
  • replace recursive midpoint and repeated-spread paths with stack-safe, allocation-efficient implementations
  • document bytewise collation and safe compaction requirements
  • make randomized benchmarks reproducible

Why

The previous conflict suffix strategy could move retry candidates outside the requested interval, especially for bounded and batched generation. Long valid inputs could also exhaust the call stack, and unbounded batch counts could trigger impractical allocations.

Impact

Generation is safer under conflicts and adversarial inputs, while preserving ordered results. A minor changeset is included because generation limits and retry behavior are now explicit API guarantees.

Validation

  • pnpm exec vp run check
  • pnpm exec vp run test (34 files, 177 tests)
  • pnpm exec vp run typecheck (core plus supported Drizzle, Prisma, and TypeScript fixtures)

Summary by CodeRabbit

  • New Features

    • Added a maximum limit of 1,000,000 generated keys per request.
    • Conflict retries now produce bounded, ordered candidates within the requested range.
    • Added validation for oversized inputs, generation counts, retry settings, and negative skips.
  • Bug Fixes

    • Long keys and midpoint calculations no longer risk call-stack exhaustion.
    • Reduced memory usage when generating multiple keys.
  • Documentation

    • Expanded guidance for database collation, indexing, input limits, compaction, batching, and performance expectations.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@SegaraRai, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 55 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a6ad155-fc16-445c-ad03-bfbfd8d45db6

📥 Commits

Reviewing files that changed from the base of the PR and between 87eb5d3 and 28c11f1.

📒 Files selected for processing (2)
  • packages/core/README.md
  • packages/core/src/factory.ts
📝 Walkthrough

Walkthrough

The change adds bounded, interval-preserving retry candidates for binary and string keys. It validates generation limits and input lengths, replaces recursive midpoint construction with iterative logic, reduces batch allocations, updates documentation, and makes benchmarks deterministic.

Changes

Fractional-index retry generation

Layer / File(s) Summary
Iterative midpoint construction
packages/core/src/lib/decimal-binary.ts, packages/core/src/lib/decimal-string.ts, packages/core/src/lib/*test.ts
Binary and string midpoint generation now uses iterative prefix processing. Long-input tests cover the new behavior.
Bounded retry API and validation
packages/core/src/factory.ts, packages/core/src/factory.test.ts, packages/core/README.md, .changeset/safe-retries-balance.md
The factories export MAX_GENERATED_KEYS, validate counts and input lengths, and generate ordered retry candidates within the requested interval. Tests and documentation cover these rules.
Efficient batch generation and benchmarks
packages/core/src/lib/fractional-indexing-*.ts, packages/core/src/lib/fractional-indexing-*.bench.ts, packages/core/README.md
Batch generation fills preallocated arrays. Random-operation benchmarks use seeded generators. Performance and compaction guidance is documented.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Factory
  participant MidpointGenerator
  Caller->>Factory: request retry keys
  Factory->>Factory: validate count and input lengths
  Factory->>MidpointGenerator: subdivide the original interval
  MidpointGenerator-->>Factory: return ordered midpoint keys
  Factory-->>Caller: return retry candidates
Loading

Poem

A rabbit checks each key in line,
And bounds the retries by design.
Midpoints march through ranges bright,
Long inputs stay safe and tight.
Seeded hops make benchmarks right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the PR's main goal of improving the safety and robustness of fractional index generation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-fractional-indexing-audit

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/core/src/lib/fractional-indexing-binary.bench.ts (1)

7-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Share the seededRandom helper between the benchmark files. Both files define byte-identical generators with the same default seed. A single shared test/bench utility guarantees the two suites keep receiving the same workload, which is the stated goal of this change.

  • packages/core/src/lib/fractional-indexing-binary.bench.ts#L7-L15: import seededRandom from a shared bench utility module instead of defining it here.
  • packages/core/src/lib/fractional-indexing-string.bench.ts#L22-L30: import the same shared seededRandom instead of defining it here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/lib/fractional-indexing-binary.bench.ts` around lines 7 -
15, Move the byte-identical seededRandom helper into a shared benchmark utility
module, then remove the local definitions and import the shared helper in
packages/core/src/lib/fractional-indexing-binary.bench.ts (lines 7-15) and
packages/core/src/lib/fractional-indexing-string.bench.ts (lines 22-30).
Preserve the existing default seed and generator behavior so both benchmarks
receive the same workload.
packages/core/src/lib/fractional-indexing-binary.ts (1)

262-283: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the duplicated balanced fill helper. Both modules now contain the same preallocate-and-fill algorithm, and only the key-generation callback differs. A shared generic helper that takes (lower, upper) => T keeps the two implementations from diverging later.

  • packages/core/src/lib/fractional-indexing-binary.ts#L262-L283: replace the local fill with a call to the shared helper, passing generateKeyBetweenUnsafe.
  • packages/core/src/lib/fractional-indexing-string.ts#L338-L359: replace the local fill with a call to the same shared helper, passing a closure that applies ...args.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/lib/fractional-indexing-binary.ts` around lines 262 - 283,
Extract the duplicated balanced preallocate-and-fill algorithm into one shared
generic helper accepting a `(lower, upper) => T` key-generation callback. In
packages/core/src/lib/fractional-indexing-binary.ts lines 262-283, replace the
local fill implementation with the helper using generateKeyBetweenUnsafe; in
packages/core/src/lib/fractional-indexing-string.ts lines 338-359, replace its
local fill implementation with the same helper using a closure that applies
...args.
packages/core/src/factory.ts (1)

596-627: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the shared internal-error message for retry-key failures.

The FraciError code is already "INTERNAL_ERROR", but these two throws use "Could not generate retry key" while the INTERNAL_ERROR documentation covers generic internal errors and asks users to file an issue. Use the existing internal-error wording here, or add the exact message to the README troubleshooting section if this message is intentional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/factory.ts` around lines 596 - 627, The retry-key failure
paths in generateRetryKey use a message inconsistent with the shared
INTERNAL_ERROR wording. Replace both “Could not generate retry key” messages
with the existing standard internal-error message, reusing the established
symbol or wording rather than adding new documentation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/README.md`:
- Around line 863-867: Update the compaction procedure in the README’s second
step to note the MAX_GENERATED_KEYS limit and instruct batching
generateNKeysBetween calls when rowCount exceeds 1,000,000, while preserving the
same total number and ordering of replacement keys.

---

Nitpick comments:
In `@packages/core/src/factory.ts`:
- Around line 596-627: The retry-key failure paths in generateRetryKey use a
message inconsistent with the shared INTERNAL_ERROR wording. Replace both “Could
not generate retry key” messages with the existing standard internal-error
message, reusing the established symbol or wording rather than adding new
documentation.

In `@packages/core/src/lib/fractional-indexing-binary.bench.ts`:
- Around line 7-15: Move the byte-identical seededRandom helper into a shared
benchmark utility module, then remove the local definitions and import the
shared helper in packages/core/src/lib/fractional-indexing-binary.bench.ts
(lines 7-15) and packages/core/src/lib/fractional-indexing-string.bench.ts
(lines 22-30). Preserve the existing default seed and generator behavior so both
benchmarks receive the same workload.

In `@packages/core/src/lib/fractional-indexing-binary.ts`:
- Around line 262-283: Extract the duplicated balanced preallocate-and-fill
algorithm into one shared generic helper accepting a `(lower, upper) => T`
key-generation callback. In packages/core/src/lib/fractional-indexing-binary.ts
lines 262-283, replace the local fill implementation with the helper using
generateKeyBetweenUnsafe; in packages/core/src/lib/fractional-indexing-string.ts
lines 338-359, replace its local fill implementation with the same helper using
a closure that applies ...args.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 47b1ada6-8671-4379-b18a-0a369a4ea06c

📥 Commits

Reviewing files that changed from the base of the PR and between 9d49514 and 87eb5d3.

📒 Files selected for processing (12)
  • .changeset/safe-retries-balance.md
  • packages/core/README.md
  • packages/core/src/factory.test.ts
  • packages/core/src/factory.ts
  • packages/core/src/lib/decimal-binary.test.ts
  • packages/core/src/lib/decimal-binary.ts
  • packages/core/src/lib/decimal-string.test.ts
  • packages/core/src/lib/decimal-string.ts
  • packages/core/src/lib/fractional-indexing-binary.bench.ts
  • packages/core/src/lib/fractional-indexing-binary.ts
  • packages/core/src/lib/fractional-indexing-string.bench.ts
  • packages/core/src/lib/fractional-indexing-string.ts

Comment thread packages/core/README.md
@SegaraRai
SegaraRai merged commit 9866b54 into main Jul 31, 2026
3 checks passed
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.

1 participant