Skip to content

[P1][kernel] Define getRange iterator semantics under concurrent mutation #17

Description

@cevheri

Summary

getRange is a lazy generator over the live working array. tx.delete (or tx.set that shifts indices) during iteration silently skips entries — the classic "delete while scanning" bug. Pattern: scan prefix, delete matches → every other entry skipped, operation reports success.

Audit ID: B6 (High) — pre-announcement blocker

Root cause

*getRange(start, end) {
  for (let i = locate(working, start).index; i < working.length; i++) {
    const entry = working[i] as StoredEntry;
    if (compareKeys(entry.key, end) >= 0) break;
    yield entry;
  }
}

Index-based walk over a mutating array.

Proposed fix (pick one)

Option A — Snapshot on first next() (recommended)

Collect matching entries (keys + values) into an array at iterator start; yield from snapshot. Cost: O(k) for range size k — acceptable for v1.

Option B — Detect modification and throw

Track working.length/version; throw libredb: getRange iterator invalidated by transaction mutation.

Either is valid; snapshot matches SQLite-style stable read in a transaction better for the delete-while-scan use case.

Tests (mandatory)

  1. Insert a, b, c in range; iterate and delete each → all three deleted.
  2. Insert-only during scan — define expected behavior (throw or snapshot).
  3. Document semantics in JSDoc on getRange.

Acceptance criteria

  • Delete-while-scanning processes every entry (no skips).
  • Behavior documented on Transaction.getRange.
  • Tests in src/core.test.ts.
  • bun run gate green.
  • Changeset if error behavior added; still changeset for documented semantic fix.

Related issues

  • Independent kernel API contract issue.

Agent constraints

  • Keep generator API; do not break sync transaction model.

Verification

bun run gate

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/kernelPre-announcement auditbugSomething isn't workingpre-announcementPre-announcement auditpriority/highPre-announcement audit

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions