Skip to content

test(master): real index builds under throttled, frozen and concurrent IO - #355

Merged
beinan merged 1 commit into
lance-format:mainfrom
beinan:test/real-index-io-stall-scenarios
Oct 8, 2026
Merged

beinan merged 1 commit into
lance-format:mainfrom
beinan:test/real-index-io-stall-scenarios

Conversation

@beinan

@beinan beinan commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Part of #333. Fixes review finding 6 on #340 (credit: production review): the earlier test used hand-placed checkpoint()s, a one-row real build, and never asserted the build outlived the idle timeout.

Scenarios (real BTree preparation, 64 rows, 3 s idle timeout)

Storage Expected Guard against vacuity
(a) every data/index op sleeps 1.2 s completes asserts ≥ 3 ops intercepted and total time > idle timeout
(b) parked after first op cancelled with exact stall error in [IDLE, IDLE+4) asserts shim saw IO
(c) healthy table concurrent with (b) completes; not cancelled; does not keep (b) alive —

Support code

  • MergeWriteScope::with_preparation_authorizer_and_io_shim: layers a shim beneath the progress wrapper, so the watchdog counts the shimmed store's completed IO exactly as real storage.
  • preparation_io::test_support::{Throttle, ThrottleWrapper} (#[doc(hidden)]).
  • Uses Lance's file-object-store:// scheme: local directory through the ObjectStore API so wrappers apply as on cloud stores (plain file paths take the direct IO fast path and bypass them — which is why the first attempt saw 0 ops).

Mutation check

Removing read-chunk + get_ranges progress accounting from ProgressStore fails (a) with slow-but-alive real build was cancelled after ~4 s. Restored.

Validation

New test + slow_but_alive_… + prepared_index_task_… pass against etcd (12 s); clippy -D warnings, fmt, typos clean.

🤖 Generated with Claude Code

…t IO

Review of lance-format#340 found its evidence insufficient: the long case used
hand-placed checkpoint() calls rather than real IO, the real build had
one row and finished instantly, and nothing asserted the build outlived
the idle timeout. This adds the three scenarios asked for, all on a
real BTree preparation over 64 rows:

(a) Throttled: every data/index store operation sleeps 1.2 s under a 3 s
    idle timeout. The build takes longer than the idle timeout in total
    and completes, because each completed operation is progress. The
    test asserts the shim intercepted at least three data operations and
    that total time exceeded the idle timeout, so it cannot pass
    vacuously.
(b) Frozen: the same build with storage parked is cancelled with the
    exact stall error within [IDLE, IDLE + 4).
(c) Isolation: a healthy preparation on another table runs concurrently
    with (b), finishes, and neither keeps (b) alive nor is cancelled by
    it.

Support: MergeWriteScope::with_preparation_authorizer_and_io_shim layers
a test shim beneath the progress wrapper so the watchdog observes the
shimmed store's completed IO exactly as it would real storage;
preparation_io::test_support::ThrottleWrapper delays or freezes
data-file IO. The test uses Lance's file-object-store scheme, which
drives a local directory through the ObjectStore API so wrappers apply
as on cloud storage (plain file paths bypass them).

Mutation check: removing read-chunk and get_ranges progress accounting
from ProgressStore fails (a) with "slow-but-alive real build was
cancelled" after ~4 s. lance-format#340's test is kept as the cheap unit-level case.

Refs lance-format#333. Review finding 6 on lance-format#340.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@beinan
beinan merged commit c3d7023 into lance-format:main Oct 8, 2026
11 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