Repository navigation
Stores now support non-exact upload sizes & S3 store optimizations - #11
Merged
Merged
Conversation
allada
force-pushed
the
s3-store-supports-estimates-and-buffers
branch
2 times, most recently
from
November 5, 2021 04:25
dac98fa to
f6da5ed
Compare
allada
commented
Nov 5, 2021
allada
left a comment
Contributor
Author
There was a problem hiding this comment.
Reviewed 29 of 32 files at r1, 5 of 7 files at r2, 1 of 1 files at r3.
Reviewable status: 34 of 35 files reviewed, all discussions resolved (waiting on @allada)
S3 store now is optimized and can upload multiple parts concurrently. Non-exact upload sizes is supported for a follow-up change which will allow compression to and from backend stores.
allada
force-pushed
the
s3-store-supports-estimates-and-buffers
branch
from
November 5, 2021 04:44
f6da5ed to
6a9b50e
Compare
allada
commented
Nov 5, 2021
allada
left a comment
Contributor
Author
There was a problem hiding this comment.
Reviewed 1 of 7 files at r2.
Reviewable status: 32 of 35 files reviewed, all discussions resolved (waiting on @allada)
rejuvenile
added a commit
to rejuvenile/nativelink
that referenced
this pull request
Aug 19, 2026
…raceMachina#12/TraceMachina#13/TraceMachina#14: minor cleanups + boundary/mode tests TraceMachina#8 (MINOR) — `fits()` defensive: added `(Some(_), Some(0)) => true` arm so a future code path that records a stale `(used, 0)` cannot lock the peer out of all picker rotations. Sits before the main `<=` arm. TraceMachina#9 (MINOR) — Reverted visibility widening on `BlobsAvailableState::fs_store` and `cas_server_fss` to private. Only consumer is in the same module (`local_worker.rs`). TraceMachina#11 (MINOR) — Replaced hand-rolled temp paths in `blobs_in_stable_storage_handler_test.rs` and `download_to_directory_mirror_test.rs` with `tempfile::Builder`. `.keep()` disarms auto-cleanup so the FilesystemStore (lives past the test body inside Arcs) doesn't see its content_path vanish mid-run. TraceMachina#12 (MINOR) — Inlined `pick_mirror_endpoint` wrapper and renamed `pick_mirror_endpoint_for_size` → `pick_mirror_endpoint`. The wrapper was only used by tests (not prod) and the duplication added cognitive load. All 5 test sites updated to pass `0` for size_bytes (preserves pre-fix behavior of disabling capacity filter). TraceMachina#13 (MINOR) — Added `test_fits_at_exact_boundary_returns_true`. Uses two peers — "a" exactly at boundary, "b" with room — and asserts the picker round-robins both. Mutate-verified: changing `<=` to `<` in `fits()` makes the test FAIL (only "b" gets picked). TraceMachina#14 (MINOR, Linux-only) — Added `mirror_materialize_sets_0o555_mode_on_disk`. Builds a FastSlowStore whose fast tier is a real FilesystemStore, runs the mirror-materialize path, then asserts the on-disk file's mode is exactly 0o555 via `digest_content_path`. Guards against a regression where the mirror-materialize path bypasses or post-overwrites the canonical CAS read-execute mode. cargo check --all-targets clean. mirror_durability_test: 15/15 pass (was 14). worker_proxy_store unit tests: 31/31 pass (was 30). Pre-existing unrelated failures in `bytestream_server_test` (locality_stale_evicts_and_ingests, locality_timeout_falls_through_without_eviction, write_too_many_bytes_fails) and `existence_store_test` (copes_with_dropped_items) are NOT caused by this commit — they fail identically on parent 70b2f59. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rejuvenile
added a commit
to rejuvenile/nativelink
that referenced
this pull request
Aug 19, 2026
…Machina#2+TraceMachina#3+TraceMachina#5+TraceMachina#9+TraceMachina#11 (BLOCK-class) Addresses 6 of 11 reviewer findings on the BlobsAvailable chunking landing (PR3 of TraceMachina#80). Each fix is annotated with the originating reviewer + finding ID. ACCUMULATOR (nativelink-service/src/blobs_available_accumulator.rs): * Fix TraceMachina#1 (invariant-prover BLOCK + dsr + code-reviewer): Add sequence-completeness gate at terminal commit. Before this fix, a terminal chunk arriving with gaps in `seen_sequences` committed a strict-subset partial — the half-applied-snapshot bug class the Path A semantics are meant to prevent. The new `BroadcastAccumulator::sequences_contiguous()` checks `seen_sequences == (1 << (max_seen_sequence + 1)) - 1`. On rejection: drop the partial accumulator, increment `dropped_incomplete_sequence` counter, warn-log, return None. Worker re-broadcasts on next tick. * Fix TraceMachina#3 (red-team BLOCK + testing-czar IMP-4 + assumption-auditor REFUTED-1): Header scalars (worker_cas_endpoint, cpu_load_pct, mirror_used_bytes, etc.) now stored as `Option<HeaderScalars>`, populated only when `sequence == 0` arrives. If the terminal commits without seq=0 ever arriving, refuse (subsumed by Fix TraceMachina#1 in practice but documented separately). `BroadcastAccumulator::new()` no longer reads scalars from "first chunk to arrive" — that path silently lost headers under out-of-order delivery. * Fix TraceMachina#2 (dsr BLOCK-1 + red-team alt 1): Raise MAX_SEQUENCES from 64 → 256 (bitset switched from u64 to u128-pair) AND MAX_ACCUMULATED_ENTRIES_PER_CONN from 200_000 → 1_000_000 to match the AC-pin per-endpoint cap of 1M. Worker FSS sizing 50K- 200K + AC pins + cached_directory_digests easily reaches 1M total; the prior 200K cap silently dropped legitimate worker traffic. * Fix TraceMachina#11 (security M1 + assumption-auditor REFUTED-2): - Pre-merge per-conn entries-cap projection: cap fires BEFORE `acc.merge(chunk)` so peak accumulator memory is bounded by `MAX_ACCUMULATED_ENTRIES_PER_CONN + MAX_ENTRIES_PER_CHUNK`, not `+ (one hostile chunk's worth)`. - Per-chunk entries cap (`MAX_ENTRIES_PER_CHUNK = 8192`): rejects oversized chunks before any per-broadcast state is touched. - Falsification test `entries_cap_drops_partial_at_2x_threshold`: drives 2× the cap of synthetic data, asserts cap eviction fires AT threshold (not far before, not after OOM). * Fix TraceMachina#9 (dsr MAJOR-1): Per-reason `chunks_dropped_*` counters exposed via `pub drop_counts: ChunkDropCounts`. 9 reasons: token_zero, token_mismatch, per_conn_broadcasts_cap, per_conn_entries_cap, per_chunk_entries_cap, sequence_cap, validation_other, incomplete_sequence, missing_chunk_zero. Each warn-log carries the reason as a structured field. Test `drop_counters_cover_all_documented_reasons` exercises 7 of 9 paths (the two missing-chunk-zero paths are structurally unreachable when the completeness gate fires first; counter exists for defense-in-depth). * Fix TraceMachina#5 (invariant-prover + assumption-auditor): Replaced `out_of_order_sequence_within_window_tolerated` with `out_of_order_sequence_with_gap_rejected`. The old test ENSHRINED THE BUG by asserting `is_some()` on a commit that skipped sequence 1 — the new test asserts `is_none()` with the bespoke message "sequence-completeness gate must reject incomplete commit; saw is_some() instead — Fix TraceMachina#1 (invariant-prover BLOCK) regression". * Removed gratuitous `total_accumulated: AtomicUsize` (code-reviewer TraceMachina#4): always accessed under the inner mutex; reduced to a plain `usize` field on `AccumulatorInner`. Adds a `total_accumulated()` test helper. CHUNKER (nativelink-util/src/blobs_available_chunking.rs): * Fix TraceMachina#2 (dsr BLOCK-1): Added `BLOBS_AVAILABLE_MAX_CHUNKS_PER_BROADCAST = 256` MUST-equal-the- server-MAX_SEQUENCES constant. Changed `chunk_blobs_available()` signature from `Vec<...>` to `Result<Vec<...>, &'static str>`. Returns Err if a broadcast would emit > 256 chunks. New tests: `chunker_errors_when_exceeding_max_chunks_per_broadcast` and `chunker_allows_exact_max_chunks_per_broadcast` (boundary). WORKER (nativelink-worker/src/local_worker.rs): * `send_periodic_blobs_available` updated to handle the chunker's new Result return: on Err, warn-log and return Ok(()) (skip the tick; next tick retries). Better than emitting chunks the server silently discards. INVARIANTS WALKED: * terminal-chunk-commits ⇒ seen_sequences forms contiguous prefix [0, max_seen_sequence] (Fix TraceMachina#1 — re-established at blobs_available_accumulator.rs `sequences_contiguous()`). * per-conn memory bound: `total_accumulated <= MAX_ACCUMULATED_ENTRIES_PER_CONN + MAX_ENTRIES_PER_CHUNK` even with a hostile chunk (Fix TraceMachina#11 — re-established at pre-merge cap-check). * chunker output count <= BLOBS_AVAILABLE_MAX_CHUNKS_PER_BROADCAST = server's MAX_SEQUENCES (Fix TraceMachina#2 — enforced at chunker producer-side guard). TESTS: * nativelink-util chunker: 11/11 pass (added 2 tests). * nativelink-service accumulator: 19/19 pass (added 7 tests, rewrote 1, removed 0). Reviewers cited: invariant-prover BLOCK, distributed-systems-reviewer BLOCK-1 + MAJOR-1, red-team blind-spot-1 + alt-1 + alt-2, testing-czar IMP-2 + IMP-3 + IMP-4, code-reviewer Critical TraceMachina#1 + suggestion TraceMachina#4, assumption-auditor REFUTED-1 + REFUTED-2, security-reviewer M1 + M2. Composite invariants this fix interacts with: Path A (deferred-wipe) commit semantics, mirror_blobs ≥2-replica durability (untouched — BlobsAvailable is locality hint only), worker_instance_token contract from TraceMachina#97/TraceMachina#98. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rejuvenile
added a commit
to rejuvenile/nativelink
that referenced
this pull request
Aug 19, 2026
…ns + T9 pin order
Cadre fix-up B3+B4+B5+T9+N1+N2 for the chunked_b1_writev_test.rs and a
stale module doc-comment in chunked_writer.rs.
B3 — io_uring skip-guards: every Path-A test now calls
`skip_if_no_io_uring(test_name)` at entry; non-Linux / non-io-uring
hosts log a SKIP and return. Without the guard, Path B
(spawn_blocking) was silently exercised and tests "passed" for the
wrong reason — invariants like T4's "different digests parallelize"
became tautologies on the spawn_blocking path.
B4 — index-visibility assertions: replaced `let _ = results` discards
at T1 and T_multi with a new `assert_index_visible` helper that:
- passes a real `&mut [Option<u64>; 1]` slot,
- awaits has_with_results within a 5 s window,
- panics with bespoke "stale negative — index not updated post-rename"
when results[0] is None,
- asserts the size matches the expected blob size.
Mutation target named in the panic message per CLAUDE.md
`feedback_index_visibility_contract` (2026-05-04).
B5 — T2 doc-comment: updated the stale "Mutation target" framing from
the prior coalesce-strict-< form (which can never fire under
COALESCE_TARGET == CHUNK_SIZE == 1 MiB) to match the design's §1/§4
load-bearing-win framing (io_uring bypass of the spawn_blocking pool
mutex, NOT coalescing amortization). Steady state IS one writev per
chunk; histogram inversion is the actual contract bug to guard.
T9 — pin-ordering correctness (cadre fix-up P1 falsification): new
`b1_writev_pin_only_advertises_post_cqe_bytes`. Injects writer error
BEFORE the first writev (N=0 trigger fires on writev_submit_count
>= 0 immediately), so NO chunk's writev CQE returns Ok. Asserts
`driver.pinned_chunk_count() == 0` and `driver.pinned_bytes() == 0`.
Mutation: comment out the populate inside `process_completion`'s
Ok-arm AND restore the driver-site populate unconditionally; T9
red-fails with the bespoke "pin advertised bytes before writev
completed" message. (Mutation verification step run in follow-up.)
N1 — chunked_writer.rs stale module doc-comment ("Phase status
(2026-06-03)") updated: wire-up, marker, helper, T1/T_multi/T_drop/
T2/T4/T5/T6/T7/T8 are all landed; cadre fix-up adds T9.
N2 — `use core::pin::Pin;` moved to the top `use` block (was
inline at the test body in the previous diff).
N3 (perf TraceMachina#11 hit_eof cleanup) — skipped: hit_eof is used for the
post-error post-EOF control flow in step 4. The proposed
`while chunk_rx.recv().await.is_some() {} break;` cleanup would
fast-forward to step 7's drain, which already exists; the duplication
is a NIT and the proposed change risks correctness regression in T8.
All 9 tests pass (T1, T_multi, T_drop, T2, T4, T5, T6, T7 unit pair,
T8, T9) on buildcache (Linux + io-uring kernel).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rejuvenile
added a commit
to rejuvenile/nativelink
that referenced
this pull request
Aug 19, 2026
…CacheStore construction Invariant: an ECS over a registered-but-ref-wrapped backend must register its invalidation callback (the ECS stale-positive triangle's eviction corner). Violated: ECS::new_with_time queried supports_removal_callbacks() on a freshly-created RefStore (cell=None) — false-for-unresolved (e8b1498/TraceMachina#367, deliberate, preserved) latched vulnerable_mode=true at EVERY boot of this binary+config; AC_INNER's eager-invalidation callback was never registered on REDIS_AC_STORE (1 of 2 callbacks). Plausibly present since the config landed ~May 11 (pre-deploy journal retention prevented earlier detection). Fix: explicit inner_store(None) resolution before the query — mirrors what FastSlowStore::new_validated does accidentally at :1445. distsys traced the post-fix composite end-to-end: callback registers on the memory tier immediately and deferred-replays onto REDIS_AC_STORE at first Redis op (notifications default-on). Boot-order safe (declaration order + graceful degradation on missing names — guarded by test). Tests: TDD red-verified (timestamp-proven chain) + mutation red with bespoke 'TraceMachina#9' message; missing-name negative-contract test; callback liveness via eviction→ECS-clear with timeout-pattern poll. [[test]] required-features stanza added (testing-czar BLOCK — plain cargo test refused clearly instead of E0599). Guard comment added on RefStore::supports_removal_callbacks against future auto-resolve cleanup. Reviewers 7/7 (records .claude/reviews/acbb767d-ecs-fix/): perf/code/ auditor/security/distsys/red-team landable; testing-czar BLOCK closed in review batch. Follow-ups: TraceMachina#10 (FastSlow sibling), TraceMachina#11 (callback-chain observability: vulnerable_mode=0 can mask a dead chain; FastSlow capability honesty; metric help-text; get_store-abort edge; production-shape propagation test). Behavior changes: AC_INNER ECS registers eager invalidation at boot; the startup vulnerable_mode ERROR no longer fires for ref-wrapped registered backends. Closes TraceMachina#9. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
rejuvenile
added a commit
to rejuvenile/nativelink
that referenced
this pull request
Aug 19, 2026
…k-chain correctness (ECS/FSS/RefStore)
## Invariant Walk
Invariant being violated: A store reporting supports_removal_callbacks()==true
must actually fire callbacks on every eviction observable to the composite;
any composition layer that returns true unconditionally without querying its
inner stores leaves ECS in a false-safe state where vulnerable_mode=false but
no callbacks ever fire.
Mechanism that violates it:
- fast_slow_store.rs: no supports_removal_callbacks override → trait default
`true` inherited unconditionally; ECS(FastSlow{*, GrpcStore}) would see
supports=true, register a dead callback, and never fire on GrpcStore-side
evictions.
- fast_slow_store.rs:756-area register_slow_eviction_stable_set_listener
called supports_removal_callbacks() on a possibly-unresolved RefStore; an
unresolved RefStore returns false by design (e8b1498/TraceMachina#367 contract), so
the BIS listener would log a false warn and skip registration.
- ref_store.rs:get_store loop: `store.register_item_callback(callback)?`
returned Err WITHOUT writing the cell — permanently bricking the RefStore;
every subsequent op re-entered the slow path and failed forever.
Mechanism that re-establishes it after the fix:
- fast_slow_store.rs: new supports_removal_callbacks override resolves both
tier stores via inner_store(None) before querying, then returns
fast.supports() && slow.supports(); ECS gets the correct composite answer.
- fast_slow_store.rs:register_slow_eviction_stable_set_listener: calls
slow_store.inner_store(None) before supports_removal_callbacks(), forcing
RefStore cell population so the capability query sees the resolved store.
- ref_store.rs:get_store: writes the cell BEFORE replaying callbacks; replay
Err is logged + counted but resolution is considered succeeded (degraded,
not bricked).
Composite invariants this fix interacts with:
- ECS vulnerable_mode triangle: gate (supports=false → vulnerable_mode=true)
OR eager-invalidation-via-callback; fix ensures the gate correctly reflects
whether callbacks can fire end-to-end.
- BIS listener registration: BIS ack requires the stable-set callback path
fires on every slow-tier eviction; TraceMachina#10 fix ensures direct FastSlowStore::new
callers with ref-wrapped slow stores don't silently lose the listener.
- RefStore resolution contract: after get_store() returns Ok, the cell is
permanently written and all ops delegate to the resolved store even if
callback replay partially failed.
Test that proves the fix re-establishes the invariant:
- capability_query_callback_chain_test.rs (all 9 tests, 0 failures):
- fast_slow_supports_callbacks_false_when_slow_does_not (TraceMachina#11 Item 2)
- fast_slow_supports_callbacks_true_when_both_tiers_support (TraceMachina#11)
- fast_slow_supports_callbacks_true_when_slow_ref_resolves_to_memory (TraceMachina#11)
- ref_store_get_store_not_bricked_by_callback_replay_failure (TraceMachina#11 Item 5)
- ecs_over_ref_fast_slow_slow_tier_eviction_clears_cache (TraceMachina#11 Item 6)
- ecs_invalidation_callbacks_fired_counter_increments (TraceMachina#11 Item 3)
- fast_slow_new_ref_wrapped_slow_registers_bis_listener (TraceMachina#10)
- ecs_over_fss_no_callback_slow_enters_vulnerable_mode (TraceMachina#11 Item 2 over-action)
- fss_supports_callbacks_false_when_fast_does_not_and_rule (TraceMachina#11 AND-rule pin)
## Changes
### Item 1 (TraceMachina#10) — resolve RefStore before BIS listener capability query
fast_slow_store.rs: `register_slow_eviction_stable_set_listener` calls
`slow_store.inner_store(None::<StoreKey<'_>>)` before
`supports_removal_callbacks()`. Forces RefStore cell population so the
unresolved-cell false-return doesn't trigger a misleading warn.
### Item 2 (TraceMachina#11) — FastSlowStore supports_removal_callbacks honesty
New `StoreDriver::supports_removal_callbacks` override on FastSlowStore
resolves both tiers via `inner_store(None)` then returns
`fast.supports() && slow.supports()`. Pre-fix: trait default `true`
inherited unconditionally. AND rule is over-conservative for ECS stale-
positive prevention (slow-only suffices) but kept as defense-in-depth.
### Item 3 (TraceMachina#11) — ECS invalidation_callbacks_fired counter
New `CounterWithTime` field on ExistenceCacheStore, incremented in the
ExistenceCacheCallback::callback path when a cache entry is actually removed.
Metric counts evictions from ANY registered tier (fast-tier LRU churn AND
slow-tier evictions); nonzero does NOT prove slow-tier chain is alive; zero
over a churn window with active writes is the meaningful dead-chain signal.
### Item 4 (TraceMachina#11) — vulnerable_mode metric help-text correction
Updated metric help to describe the actual condition (construction-time
supports_removal_callbacks()==false) rather than the incorrect prior text
("register_item_callback failed at construction").
### Item 5 (TraceMachina#11) — RefStore cell-write-before-replay no-brick fix
ref_store.rs:get_store: writes the cell unconditionally before the callback
replay loop. Replay errors are degradations (log + counter), not failures.
New `callback_replay_failures: AtomicU64` metric field.
### Item 6 (TraceMachina#11) — Production-shape propagation test
New test `ecs_over_ref_fast_slow_slow_tier_eviction_clears_cache` exercises
the full AC-chain shape: ECS(RefStore→FastSlow{Memory, Memory}). Verifies
slow-tier eviction propagates via FastSlow fanout to ECS cache removal
within a 3-second deadline.
## AND Rule: Invariant + Correctness
FSS.supports_removal_callbacks() returns fast.supports() && slow.supports().
Only slow-tier evictions create ECS stale positives (fast-tier eviction while
slow still holds the blob = false negative, self-correcting). So slow.supports()
alone is sufficient; AND is defense-in-depth. A future fast tier returning
supports=false (e.g. WorkerProxyStore) would put ECS in vulnerable_mode=true
unnecessarily; revisit the rule then.
## Behavior Changes
FastSlowStore::supports_removal_callbacks: prior → new
FastSlow{Memory, Memory}: true (default) → true (explicit; no change)
FastSlow{Memory, GrpcStore}: true (default, wrong) → false (correct)
GrpcStore.supports=false per ce4d2ec/TraceMachina#367 original commit (grpc_store.rs:3468)
FastSlow{Memory, RefStore(Memory)}: true (default) → true (after resolve)
FastSlow{Memory, NoCallbackStore}: true (default, wrong) → false (correct)
Production compositions (verified against /srv/nativelink/buildcache-native.json5):
cas_FAST_SLOW_STORE = FSS{MemoryStore, FilesystemStore} (line 111-140)
fast = plain MemoryStore (not SizePartitioningStore; SPS lives at cas_INNER
level as the ECS backend). fast.supports=true, slow.supports=true.
Composite stays true. No behavior flip. No ECS wraps directly.
AC_BACKEND_CACHED = FSS{MemoryStore, RefStore(RedisStore)} (line ~66-area)
Redis slow (enable_keyspace_notifications default true):
composite stays true. NO flip. vulnerable_mode stays false, matching
TraceMachina#9 deploy verification (vulnerable_mode=0).
SMALL_CAS_CACHED = FSS{MemoryStore, RefStore(REDIS_CAS_SMALL)} (line 206-220)
keyspace default true → composite true. No flip.
Mutations verified red:
MUTATION-1 (TraceMachina#10 inner_store resolution): observability-only — no behavioral
falsifier exists; the callback fires via RefStore queuing regardless; the
fix corrects which warn arm fires. No mutation evidence claimed.
MUTATION-2: remove supports_removal_callbacks from FastSlowStore → tests
fast_slow_supports_callbacks_false_when_slow_does_not,
ecs_over_fss_no_callback_slow_enters_vulnerable_mode,
fss_supports_callbacks_false_when_fast_does_not_and_rule all fail with
bespoke messages.
MUTATION-3: remove invalidation_callbacks_fired.inc() → test
ecs_invalidation_callbacks_fired_counter_increments fails with bespoke
"TraceMachina#11: invalidation_callbacks_fired counter did not increment after eviction"
MUTATION-5: re-add `return Err(err)` in replay loop → test
ref_store_get_store_not_bricked_by_callback_replay_failure fails with bespoke
"TraceMachina#11: ref bricked by callback replay failure"
MUTATION (new test a): revert supports_removal_callbacks to true →
ecs_over_fss_no_callback_slow_enters_vulnerable_mode red-fails with bespoke
"TraceMachina#11 over-action: ECS(FSS{Mem, NoCallback}) must enter vulnerable_mode=true..."
MUTATION (new test b): flip AND to || →
fss_supports_callbacks_false_when_fast_does_not_and_rule red-fails with bespoke
"TraceMachina#11 AND-rule: FSS{NoCallback-fast, Memory-slow}.supports() must be false..."
Cargo churn: tokio-epoll-uring exclude (Cargo.toml) + assert-panic/os_pipe
removals from Cargo.lock were NOT required for this branch to build
(verified: cargo check -p nativelink-store clean without exclude); reverted.
Bench scope: observability + callback-path (not data-plane hot path). Exempt
from data_plane_bench per CLAUDE.md (no ByteStream/FastSlow/FilesystemStore
hot-path changes).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
S3 store now is optimized and can upload multiple parts concurrently.
Non-exact upload sizes is supported for a follow-up change which
will allow compression to and from backend stores.
This change is