Skip to content

feat(parquet): Store listing wrapper for the RFC 0019 querier/compactor migration - #290

Merged
jensholdgaard merged 4 commits into
mainfrom
rfc0019-green-querier-store
Jun 24, 2026
Merged

feat(parquet): Store listing wrapper for the RFC 0019 querier/compactor migration#290
jensholdgaard merged 4 commits into
mainfrom
rfc0019-green-querier-store

Conversation

@jensholdgaard

@jensholdgaard jensholdgaard commented Jun 23, 2026

Copy link
Copy Markdown
Owner

What

RFC 0019 slice-2 prerequisite: a Store listing method, the shared seam the querier (2a) and compactor (2b) need to enumerate partitions/files on object storage instead of std::fs.

How

  • Store::list_blocking(prefix: Option<&str>) -> Result<Vec<String>, StoreError> over ObjectStore::list, drained with TryStreamExt::try_collect and run through the existing off-runtime bridge (like get_blocking/put_blocking). Recursive, prefix-scoped, returns store-relative keys (the same key space as get/put) — so the same enumeration targets LocalFileSystem (dev/test) or S3 (RFC 0019 §3.3).
  • Adds a futures dep (only TryStreamExt; already in the tree transitively via object_store).

Tests

  • Local unit test (store::tests::list_blocking_enumerates_keys_under_a_prefix): prefix-scoped → only that tenant's objects; no prefix → whole store; non-matching prefix → empty.
  • store_list_enumerates_keys_on_s3#[ignore]d localstack test proving recursive, prefix-scoped, store-relative listing on the real AmazonS3 backend (runs in the s3-integration CI job).
  • cargo clippy -p ourios-parquet --all-targets --all-features -- -D warnings clean; cargo fmt --all --check green.

Note

No §5 scenario flips green here — this is an enabling step. RFC 0019 stays red. Next: slice 2a migrates the querier read path (DataFusion register_object_store + the audit/alias/template-registry helpers) onto Store, then 2b the compactor (+ publish_cas), then slice 3 the localstack e2e (.2/.3/.4/.5) → green. Tenant isolation (RFC0019.5) is preserved structurally — the querier always builds the explicit tenant_id=<enc>/ path.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added recursive object key enumeration to the Store via list_blocking, with optional prefix filtering and deterministic lexicographic ordering. Returned keys are store-relative.
  • Tests

    • Added a unit test covering scoped prefix isolation (including exclusion of string-prefix siblings) and correct ordering for both scoped and full listings.
    • Added an ignored S3 integration test validating list_blocking against an S3-compatible backend.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bac1f549-2df3-4ea7-a63a-9df066e31088

📥 Commits

Reviewing files that changed from the base of the PR and between dfbacd3 and 75028be.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • crates/ourios-parquet/Cargo.toml
  • crates/ourios-parquet/src/store.rs
  • crates/ourios-parquet/tests/rfc0013_object_store.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/ourios-parquet/Cargo.toml
  • crates/ourios-parquet/tests/rfc0013_object_store.rs

📝 Walkthrough

Walkthrough

Adds Store::list_blocking for prefix-scoped object listing, backed by an async list helper that normalizes returned keys and sorts them. A new futures dependency supports stream collection, and unit plus S3 tests cover scoped and full listings.

Changes

Store listing capability

Layer / File(s) Summary
Dependency, imports, and listing implementation
crates/ourios-parquet/Cargo.toml, crates/ourios-parquet/src/store.rs
Adds futures for stream collection, updates object_store imports, implements async list, and adds the synchronous list_blocking bridge.
Unit and S3 integration tests
crates/ourios-parquet/src/store.rs, crates/ourios-parquet/tests/rfc0013_object_store.rs
Adds local-store and LocalStack coverage for scoped, whole-store, and non-matching prefix listings with exact lexicographic order checks.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐇 I hop through keys both near and far,
From tenant nests to every star.
I drain the stream, then line them neat,
Sorted paths in rabbit beat.
One prefix, many keys to see —
list_blocking sings: “Hooray for me!” 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, specific, and accurately reflects the new Store listing wrapper for RFC 0019 migration.
Description check ✅ Passed The description covers purpose, implementation, tests, and RFC context, but it doesn't follow the template headings exactly.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rfc0019-green-querier-store

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.

Add `Store::list_blocking(prefix)` (over `ObjectStore::list`, drained via the
off-runtime bridge like the other blocking methods): recursive, prefix-scoped,
returns store-relative keys. This is the seam the querier and compactor will
walk instead of `std::fs` (RFC 0019 §3.3) so the same enumeration targets
`LocalFileSystem` or S3 — the shared prerequisite for slices 2a/2b.

Adds a `futures` dep (TryStreamExt::try_collect, already in the tree via
object_store). Tested: a local unit test (prefix-scoped / whole-store / empty),
plus a localstack-ignored S3 test proving listing on the real AmazonS3 backend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jensholdgaard
jensholdgaard force-pushed the rfc0019-green-querier-store branch from dfbacd3 to ec5f055 Compare June 23, 2026 12:11

@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

🤖 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 `@crates/ourios-parquet/src/store.rs`:
- Around line 422-430: Remove the claim about lexicographic ordering from the
documentation comment for the list method. The doc comment currently states
results are returned "in the backend's lexicographic order," but object_store
0.13's list method does not guarantee any specific ordering. Update the first
sentence of the doc comment to remove the ordering guarantee and replace it with
a statement that the order of results is unspecified, such as "List every object
key under `prefix` (store-relative), recursively. The order of results is
unspecified."
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1f0748a3-0a65-461d-8213-51a32349f542

📥 Commits

Reviewing files that changed from the base of the PR and between dade7a9 and dfbacd3.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • crates/ourios-parquet/Cargo.toml
  • crates/ourios-parquet/src/store.rs
  • crates/ourios-parquet/tests/rfc0013_object_store.rs

Comment thread crates/ourios-parquet/src/store.rs Outdated

Copilot AI 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.

Pull request overview

This PR adds a Store-level listing API to support RFC 0019’s querier/compactor migration away from direct std::fs traversal, allowing both local and S3 backends to be enumerated through the same abstraction.

Changes:

  • Added Store::list_blocking(prefix) implemented over ObjectStore::list and bridged through the existing off-runtime blocking mechanism.
  • Added unit + ignored localstack integration tests verifying recursive, prefix-scoped, store-relative key enumeration.
  • Added a direct futures dependency for TryStreamExt::try_collect.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.

File Description
crates/ourios-parquet/src/store.rs Adds async listing + blocking wrapper and a local unit test for prefix-scoped enumeration.
crates/ourios-parquet/tests/rfc0013_object_store.rs Adds an ignored localstack S3 integration test for list_blocking.
crates/ourios-parquet/Cargo.toml Adds futures dependency for draining the listing stream.
Cargo.lock Records the new direct dependency edge on futures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/src/store.rs Outdated
Comment thread crates/ourios-parquet/tests/rfc0013_object_store.rs Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/src/store.rs
jensholdgaard added a commit that referenced this pull request Jun 23, 2026
…tore::list (Copilot/CodeRabbit #290)

- Sort the keys before returning so the order is a deterministic lexicographic
  contract, not the backend's stream order (neither LocalFileSystem nor S3
  guarantees one); reword the doc to "lexicographic order" (drop "backend's").
- Strip the prefix the correct direction (`location.prefix_match(root)`) and
  `filter_map` out non-matching entries instead of falling back to an absolute
  key — so an S3 string-prefix sibling (`ourios2/…` under `ourios`) can't leak.
- Tests (unit + localstack) now assert the returned order directly, no
  test-side sort, so an ordering regression fails the test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jensholdgaard
jensholdgaard requested a review from Copilot June 23, 2026 14:10

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

…e::list (#290)

- Sort the keys before returning so the order is a deterministic lexicographic
  contract, not the backend's stream order (neither LocalFileSystem nor S3
  guarantees one); reword the doc to "lexicographic order".
- Strip the prefix the correct direction (`location.prefix_match(root)`) and
  `filter_map` out non-matching entries instead of falling back to an absolute
  key — so an S3 string-prefix sibling (`ourios2/…` under `ourios`) can't leak.
- Tests (unit + localstack) assert the returned order directly, no test-side
  sort, so an ordering regression fails the test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.

Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/src/store.rs
Comment thread crates/ourios-parquet/tests/rfc0013_object_store.rs
Comment thread crates/ourios-parquet/tests/rfc0013_object_store.rs
…290)

S3's `list` does string-prefix matching, so listing `tenant_id=a` can return
the sibling `tenant_id=ab/…` — a tenant-isolation leak (RFC0019.5). The filter
checked only the (empty) store root, not the requested prefix. Now gate each
object on `prefix_match(&scoped)` (segment-wise, so siblings are excluded)
before stripping the root. Tests (unit + localstack) add a `tenant_id=ab`
fixture: the scoped list excludes it, the unscoped list includes it (in
lexicographic order, `tenant_id=a/` before `tenant_id=ab/`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

Comment thread crates/ourios-parquet/tests/rfc0013_object_store.rs
Comment thread crates/ourios-parquet/src/store.rs Outdated
…rd (Copilot #290)

- The localstack `list_blocking(None)` assertion now includes the
  `tenant_id=ab` fixture (in lexicographic order), so the whole-bucket
  listing is complete and a dropped-key regression would fail.
- Reword the `prefix_match(&scoped)` comment: binding to `_` marks the
  #[must_use] iterator used, it doesn't "consume" it.

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

@jensholdgaard
jensholdgaard merged commit dcf8917 into main Jun 24, 2026
22 checks passed
@jensholdgaard
jensholdgaard deleted the rfc0019-green-querier-store branch June 24, 2026 21:09
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.

2 participants