Extracts an AsyncBackend trait in kei-store so future GCS/Azure/Bunny
backends implement 5 async fns, not re-invent the sync-over-tokio
bridge. Closes architect P1 + P2 findings.
NEW src/async_backend.rs (189 LOC):
- trait AsyncBackend with get/put/list/list_recursive/delete/exists
- AsyncBackendStore<B: AsyncBackend> — generic MemoryStore impl
(sync-over-async via shared runtime)
- shared_runtime() -> &'static Runtime via OnceLock
(multi-thread, 2 workers, enable_io+enable_time)
- path helpers (validate_rel, short_hash, is_manifest_key) moved
here as single source of truth
NEW src/s3_cloud/backend.rs (120 LOC):
- S3AsyncBackend impl of AsyncBackend — 5 async fns using the
existing aws-sdk-s3::Client
MODIFIED src/s3_cloud/mod.rs (200 → 43 LOC):
pub type S3CloudStore = AsyncBackendStore<S3AsyncBackend>;
Thin re-export + inherent new(cfg) constructor.
Doc-header documents the extension seam: 'adding GCS = impl 5 async fns'.
MODIFIED src/s3_cloud/keys.rs (66 → 40 LOC): compat shim — re-exports
validate_rel / short_hash / is_manifest_key from async_backend.
Old call-sites + 4 unit tests unchanged.
Deps: async-trait = 0.1 added under s3 feature; tokio now has
rt-multi-thread feature too.
FIXES N=2 Store footgun: prior impl created a current_thread Runtime
per instance — 2 instances in one process = 2 runtimes, block_on
panic if caller is on another runtime. Shared multi-thread runtime
via OnceLock means N instances all share 2 workers.
REAL VERIFICATION (agent-pasted):
cargo check -p kei-store: clean
cargo check -p kei-store --features s3: clean
cargo test -p kei-store --release: 10+9+0 = 19 passed
cargo test -p kei-store --features s3 --release: 38+9+6 = 53 passed
(+7 vs baseline 46)
Tests added (7):
async_backend::tests::shared_runtime_is_singleton
async_backend::tests::validate_rel_rejects_absolute
async_backend::tests::validate_rel_rejects_parent
async_backend::tests::short_hash_deterministic
async_backend::tests::is_manifest_key_matches_format
s3_cloud::tests::async_backend_shared_runtime_handles_two_store_instances
s3_cloud::tests::async_backend_runtime_is_multi_thread
Public API preserved: S3CloudStore::new / .branch / .current_branch /
.key / .backend_name. Factory + integration tests untouched.
Pre-existing: list_inner 38 LOC (moved verbatim from mod.rs, not
refactored per Core Rule 3).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
1.3 KiB
TOML
38 lines
1.3 KiB
TOML
[package]
|
|
name = "kei-store"
|
|
version = "0.1.0"
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
description = "Memory-repo backend abstraction — GitHub/Forgejo/Gitea/Filesystem/S3 (v0.21.0)"
|
|
|
|
[[bin]]
|
|
name = "kei-store"
|
|
path = "src/main.rs"
|
|
|
|
[lib]
|
|
path = "src/lib.rs"
|
|
|
|
[features]
|
|
# Default: no cloud deps. S3 backend behaves as the v0.14 local-manifest stub
|
|
# (gated by KEI_STORE_ALLOW_S3_STUB=1). Users who actually need real S3 / R2 /
|
|
# MinIO push opt into the heavier AWS SDK stack by enabling this feature.
|
|
default = []
|
|
s3 = ["dep:aws-config", "dep:aws-sdk-s3", "dep:aws-credential-types", "dep:tokio", "dep:async-trait"]
|
|
|
|
[dependencies]
|
|
clap = { workspace = true }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
anyhow = "1"
|
|
toml = "0.8"
|
|
git2 = { version = "0.19", default-features = false }
|
|
|
|
# v0.21 — optional cloud stack behind `s3` feature.
|
|
aws-config = { version = "1", default-features = false, features = ["behavior-version-latest", "rustls", "rt-tokio"], optional = true }
|
|
aws-sdk-s3 = { version = "1", default-features = false, features = ["behavior-version-latest", "rustls", "rt-tokio"], optional = true }
|
|
aws-credential-types = { version = "1", optional = true }
|
|
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"], optional = true }
|
|
async-trait = { version = "0.1", optional = true }
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|