Skip to content

Store the container registry through object_store - #1043

Draft
epompeii wants to merge 3 commits into
u/ep/s3-r2/server-backupfrom
u/ep/s3-r2/registry-storage
Draft

epompeii wants to merge 3 commits into
u/ep/s3-r2/server-backupfrom
u/ep/s3-r2/registry-storage

Conversation

@epompeii

@epompeii epompeii commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

The container registry storage crate carried two hand-written backends: one on the AWS SDK, addressed by an S3 access point ARN, and one on the local filesystem. This replaces both with one implementation over the object_store crate, so any S3-compatible endpoint works through a bucket, an endpoint, and a region, and the local backend is object_store's filesystem store.

Changes

  • One OciStorage over Arc<dyn ObjectStore> replaces OciS3Storage and OciLocalStorage. Uploads keep their session shape (chunks as objects under _uploads/, a small state.json); completion streams the chunks through a multipart upload opened directly on the final blob key and aborts on a digest mismatch, so no temporary object and no copy.
  • The config section moves from plus.registry.data_store to plus.registry.storage with scheme: file | s3, mirroring the disaster recovery replica field for field. file takes an optional path; s3 takes bucket, path, endpoint, region (default auto), credentials, and chunk_size.
  • Stored keys and the on-disk layout are pinned byte for byte by key layout tests, with and without a prefix, including non-ASCII and # prefixes. A multipart boundary test pins reassembly across several parts.
  • The S3 client runs with no total request deadline and a 5 minute read timeout that resets on every body frame. object_store's default 30 s deadline, measured until the body finishes, cut any blob download or part upload that took longer. Two paused-time tests against a mock store pin both halves: a body that streams slowly past the old deadline completes, and a store that stalls after its headers fails at the read timeout.
  • Completion sizes multipart parts so the largest allowed body fits in S3's 10,000 part limit, rather than failing at part 10,001 after streaming everything.
  • The stale upload sweep is owned by the storage and stopped at shutdown, the way callbacks are drained, instead of being a detached task.
  • After every upload round trip, the store is listed and only the blob may remain, which catches a chunk written outside its session prefix.
  • An ignored live test (tests/s3_live.rs) runs the full flow against a scratch bucket from environment variables and cleans up after itself; it never runs in CI.
  • aws-sdk-s3 and aws-credential-types leave the workspace; object_store (aws, fs) and sync_wrapper arrive. The lockfile change is additions plus the AWS tree's removal, no version bumps.
  • Docs in all 9 languages describe the new section, the prefix normalization (leading, trailing, and repeated slashes dropped; control characters, non-ASCII characters, and a small reserved set such as #, %, ?, and * percent-encoded, while +, spaces, =, @, and : are kept as is), and recommend a lifecycle rule that aborts incomplete multipart uploads.

Breaking changes

  • plus.registry.data_store is replaced by plus.registry.storage. A config that still carries data_store is ignored and the registry falls back to local files.
  • A configured path that began or ended with a slash, or contained a percent-encoded character, stored objects under a different key prefix in the previous release; that data must be moved to the normalized prefix. Plain prefixes are unchanged.

Last of a stack of three, on top of the plus.disaster_recovery rename and the on demand backup removal.

@epompeii
epompeii added this pull request to stack #1042 September 18, 2026 07:13
@socket-security

socket-security Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​object_store@​0.14.28110090100100
Addedcargo/​base64@​0.23.110010093100100

View full report

@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

ProjectBencher
Branchu/ep/s3-r2/registry-storage
Testbedintel-v1
Click to view all benchmark results
BenchmarkLatencyBenchmark Result
microseconds (µs)
(Result Δ%)
Upper Boundary
microseconds (µs)
(Limit %)
Adapter::Json📈 view plot
🚷 view threshold
5.24 µs
(+5.45%)Baseline: 4.97 µs
6.07 µs
(86.31%)
Adapter::Magic (JSON)📈 view plot
🚷 view threshold
5.04 µs
(+4.93%)Baseline: 4.80 µs
5.76 µs
(87.53%)
Adapter::Magic (Rust)📈 view plot
🚷 view threshold
27.76 µs
(+3.62%)Baseline: 26.79 µs
30.26 µs
(91.75%)
Adapter::Rust📈 view plot
🚷 view threshold
4.81 µs
(+15.59%)Baseline: 4.16 µs
6.53 µs
(73.74%)
Adapter::RustBench📈 view plot
🚷 view threshold
4.82 µs
(+15.89%)Baseline: 4.16 µs
6.52 µs
(73.96%)
🐰 View full continuous benchmarking report in Bencher

@epompeii
epompeii marked this pull request as ready for review September 18, 2026 07:47
@epompeii
epompeii marked this pull request as draft October 1, 2026 02:26
The continuous replication section was named plus.litestream in code,
with disaster_recovery only as a serde alias, while the docs named
plus.disaster_recovery. Rename the type and field to the documented key
and drop the alias. Also drop the unused sftp replica scheme, so the
section reads scheme: file | s3, and fix the docs example, which showed
a replicas array the code never accepted.
The POST /v0/server/backup endpoint, the bencher server backup CLI
subcommand, and the database.data_store server config section are gone.
Continuous replication under plus.disaster_recovery is the supported
path, so bencher_schema no longer depends on the AWS SDK.
A config that still carries database.data_store is ignored.
Replace the hand-written S3 and local filesystem backends with one
implementation over `object_store`, so any S3-compatible endpoint works
through a bucket, endpoint, and region instead of an access point ARN.
The config section becomes `plus.registry.storage` with `scheme: file |
s3`, matching the disaster recovery section. Stored keys and the local
directory layout are unchanged for a plain prefix, pinned by key layout
tests; see the config reference for slash-edged prefixes and prefixes
with characters the store percent-encodes.
@epompeii
epompeii force-pushed the u/ep/s3-r2/registry-storage branch from 0bad79d to 553b70c Compare October 1, 2026 06:14
@epompeii
epompeii marked this pull request as ready for review October 1, 2026 06:47
@epompeii
epompeii marked this pull request as draft October 3, 2026 19:02
@epompeii epompeii added the deploy label Oct 3, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant