feat(parquet): route the manifest through the object-store seam (rfc0013 green) - #234
Conversation
…013 green) Wire the RFC 0009 per-partition manifest read/write onto the RFC 0013 `Store` seam (local backend), behaviour-preserving: - `Manifest::read` reads via `Store::local(partition_dir).get_blocking_opt`, guarded by a `try_exists` check so an absent partition directory still maps to `Ok(None)` (the prior `std::fs` NotFound→None contract; `Store::local` canonicalises its root and would otherwise error on a missing dir). - `Manifest::write_atomic` writes via `Store::put_blocking`. object_store's local put stages to a private temp object and renames it into place, so the atomic-commit-point and no-fsync semantics are unchanged from the prior tmp+rename — last-writer-wins `Overwrite`. New `Store` primitives: - `get_blocking_opt` (NotFound→None) + `StoreError::is_not_found`. - `put_if_absent` / `put_if_absent_blocking` (create-if-absent, If-None-Match) — the local-testable half of RFC 0013 conditional PUT. The generation compare-and-swap (RFC0013.3/.4) is deferred to the S3 backend: `LocalFileSystem` rejects `PutMode::Update`, so CAS can't be implemented or tested on the local backend. Every existing RFC 0009 manifest + compaction suite passes unchanged through the seam. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 43 minutes and 7 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughExtends ChangesManifest I/O migration to Store abstraction
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
Routes RFC 0009 per-partition manifest I/O through the RFC 0013 Store object-storage seam (local backend), keeping on-disk format and atomicity semantics behavior-preserving while preparing for future S3 support.
Changes:
- Added
StoreError::is_not_found,Store::get_blocking_opt, and conditional create primitives (put_if_absent{,_blocking}) usingPutMode::Create. - Updated
Manifest::{read,write_atomic}to useStore::local(...).get_blocking_opt(...)/put_blocking(...), with atry_existsguard to preserve the prior NotFound→Ok(None)behavior for missing partition dirs. - Added unit tests for
get_blocking_optmissing→Nonemapping andput_if_absentrefusing to clobber.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/ourios-parquet/src/store.rs | Extends the storage seam with not-found detection, optional-get, and create-if-absent put + tests. |
| crates/ourios-parquet/src/manifest.rs | Re-routes manifest reads/writes through Store while preserving the prior absence semantics and atomic overwrite behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The sync→async bridge built a fresh tokio runtime on every *_blocking call. Manifest::read goes through it once per partition, and the querier's resolve_live_files (on its async task) walks every partition per query — so a multi-partition query paid a runtime build per partition on the hot path. Build the runtime once via OnceLock::get_or_init (multi-thread, 1 worker) and reuse it. get_or_init can't drop a surplus runtime on a caller thread the way the earlier manual get/set could (that flaked with "drop a runtime in async context" when the loser was inside a #[tokio::test]); the runtime lives for the process and is never dropped. The build Result is cached so failure still surfaces as StoreError::Runtime without an expect. The per-call scoped thread stays — it's required so block_on runs off the caller's tokio context — but it no longer also builds a runtime. rt-multi-thread is back (a shared runtime is driven by concurrent block_on from many bridge threads; a current-thread runtime can't). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RFC 0013 green slice 4 — wires the RFC 0009 per-partition manifest onto the
Storeseam (local backend), behavior-preserving. Companion to the reader seam (#233).What
Manifest::read→Store::local(partition_dir).get_blocking_opt(MANIFEST_FILENAME), guarded bytry_existsso an absent partition dir still maps toOk(None)(the priorstd::fsNotFound→None contract —Store::localcanonicalises its root and would otherwise error on a missing dir).Manifest::write_atomic→Store::put_blocking. object_store's localputstages to a private temp object then renames into place, so the atomic-commit-point + no-fsync semantics are identical to the priormanifest.json.tmp+ rename. Last-writer-winsOverwrite, unchanged.Storeprimitives:get_blocking_opt(NotFound→None) +StoreError::is_not_found;put_if_absent/put_if_absent_blocking(create-if-absent,If-None-Match) — the local-testable half of RFC 0013 conditional PUT.Deferred (by design)
The generation compare-and-swap (RFC0013.3 contention, .4 CAS half) lands with the S3 backend:
object_store's LocalFileSystemput_optsreturnsNotImplementedforPutMode::Update, so CAS can't be implemented or tested on the local backend. S3 testing will use real S3-compatible storage (Hetzner), not MinIO/LocalStack.Invariants / scope
cargo testgreen). New unit tests coverget_blocking_opt(missing→None) andput_if_absent(refuses to clobber).🤖 Generated with Claude Code
Summary by CodeRabbit