refactor(storage): narrow resync metadata bounds (#3345)

This commit is contained in:
安正超
2026-06-11 12:41:15 +08:00
committed by GitHub
parent ee96e194a3
commit 2f7cc7cb9e
3 changed files with 62 additions and 53 deletions
@@ -27,7 +27,7 @@ use crate::bucket::replication::replication_state::ReplicationStats;
use crate::config::com::read_config; use crate::config::com::read_config;
use crate::disk::BUCKET_META_PREFIX; use crate::disk::BUCKET_META_PREFIX;
use crate::error::Error as EcstoreError; use crate::error::Error as EcstoreError;
use crate::store_api::ObjectInfo; use crate::store_api::{ObjectIO, ObjectInfo};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use rustfs_filemeta::MrfReplicateEntry; use rustfs_filemeta::MrfReplicateEntry;
use rustfs_filemeta::ReplicateDecision; use rustfs_filemeta::ReplicateDecision;
@@ -976,7 +976,7 @@ impl<S: StorageAPI> ReplicationPool<S> {
} }
/// Load bucket resync metadata from disk /// Load bucket resync metadata from disk
async fn load_bucket_resync_metadata<S: StorageAPI>( async fn load_bucket_resync_metadata<S: ObjectIO>(
bucket: &str, bucket: &str,
obj_api: Arc<S>, obj_api: Arc<S>,
) -> Result<BucketReplicationResyncStatus, EcstoreError> { ) -> Result<BucketReplicationResyncStatus, EcstoreError> {
@@ -32,7 +32,7 @@ use crate::event_notification::{EventArgs, send_event};
use crate::global::GLOBAL_LocalNodeName; use crate::global::GLOBAL_LocalNodeName;
use crate::global::get_global_bucket_monitor; use crate::global::get_global_bucket_monitor;
use crate::set_disk::get_lock_acquire_timeout; use crate::set_disk::get_lock_acquire_timeout;
use crate::store_api::{DeletedObject, HTTPRangeSpec, ObjectInfo, ObjectOptions, ObjectToDelete, WalkOptions}; use crate::store_api::{DeletedObject, HTTPRangeSpec, ObjectIO, ObjectInfo, ObjectOptions, ObjectToDelete, WalkOptions};
use crate::{StorageAPI, new_object_layer_fn}; use crate::{StorageAPI, new_object_layer_fn};
use aws_sdk_s3::error::{ProvideErrorMetadata, SdkError}; use aws_sdk_s3::error::{ProvideErrorMetadata, SdkError};
use aws_sdk_s3::operation::head_object::{HeadObjectError, HeadObjectOutput}; use aws_sdk_s3::operation::head_object::{HeadObjectError, HeadObjectOutput};
@@ -485,7 +485,7 @@ impl ReplicationResyncer {
} }
} }
pub async fn mark_status<S: StorageAPI>(&self, status: ResyncStatusType, opts: ResyncOpts, obj_layer: Arc<S>) -> Result<()> { pub async fn mark_status<S: ObjectIO>(&self, status: ResyncStatusType, opts: ResyncOpts, obj_layer: Arc<S>) -> Result<()> {
let bucket_status = { let bucket_status = {
let mut status_map = self.status_map.write().await; let mut status_map = self.status_map.write().await;
let now = OffsetDateTime::now_utc(); let now = OffsetDateTime::now_utc();
@@ -590,7 +590,7 @@ impl ReplicationResyncer {
bucket_status.last_update = Some(now); bucket_status.last_update = Some(now);
} }
pub async fn persist_to_disk<S: StorageAPI>(&self, cancel_token: CancellationToken, api: Arc<S>) { pub async fn persist_to_disk<S: ObjectIO>(&self, cancel_token: CancellationToken, api: Arc<S>) {
let mut interval = tokio::time::interval(RESYNC_TIME_INTERVAL); let mut interval = tokio::time::interval(RESYNC_TIME_INTERVAL);
let mut last_update_times = HashMap::new(); let mut last_update_times = HashMap::new();
@@ -635,7 +635,7 @@ impl ReplicationResyncer {
} }
} }
async fn resync_bucket_mark_status<S: StorageAPI>(&self, status: ResyncStatusType, opts: ResyncOpts, storage: Arc<S>) { async fn resync_bucket_mark_status<S: ObjectIO>(&self, status: ResyncStatusType, opts: ResyncOpts, storage: Arc<S>) {
if let Err(err) = self.mark_status(status, opts.clone(), storage.clone()).await { if let Err(err) = self.mark_status(status, opts.clone(), storage.clone()).await {
error!("Failed to mark resync status: {}", err); error!("Failed to mark resync status: {}", err);
} }
@@ -1026,7 +1026,7 @@ pub async fn get_heal_replicate_object_info(oi: &ObjectInfo, rcfg: &ReplicationC
} }
} }
pub(crate) async fn save_resync_status<S: StorageAPI>( pub(crate) async fn save_resync_status<S: ObjectIO>(
bucket: &str, bucket: &str,
status: &BucketReplicationResyncStatus, status: &BucketReplicationResyncStatus,
api: Arc<S>, api: Arc<S>,
+55 -46
View File
@@ -5,16 +5,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
## Current Context ## Current Context
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
- Branch: `overtrue/arch-storage-api-bound-narrowing` - Branch: `overtrue/arch-replication-resync-bounds`
- Baseline: `origin/main` at `6b86e3875c4912f3a7c27915b0bbd43399402847` - Baseline: `origin/main` at `7191a3abae08918eedb117955280dc81e65450de`
- PR type for this branch: `dependency-migration` - PR type for this branch: `dependency-migration`
- Runtime behavior changes: none. - Runtime behavior changes: none.
- Rust code changes: narrow metadata helper generic bounds away from full - Rust code changes: narrow replication resync metadata helper generic bounds
`StorageAPI` where helpers only need object I/O, object metadata/delete, away from full `StorageAPI` where helpers only need object I/O.
bucket listing, object listing, or `StorageAdminApi`.
- CI/script changes: none. - CI/script changes: none.
- Docs changes: record API-008 completion and the current bound-narrowing - Docs changes: record API-009 completion and the current replication resync
context, verification evidence, and expert review outcomes. metadata bound-narrowing context, verification evidence, and expert review
outcomes.
## Phase 0 Tasks ## Phase 0 Tasks
@@ -226,25 +226,35 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
`new_ns_lock`, while admin inventory surfaces live only on `new_ns_lock`, while admin inventory surfaces live only on
`StorageAdminApi`. `StorageAdminApi`.
- [~] `API-009` Narrow metadata helper storage bounds. - [x] `API-009` Narrow metadata helper storage bounds.
- Current branch slice: narrow server config, tier config, rebalance - Completed slice: `rustfs/rustfs#3343` narrowed server config, tier config,
metadata, and startup metadata migration helper bounds away from full rebalance metadata, and startup metadata migration helper bounds away from
`StorageAPI` when the helper only needs `ObjectIO`, `ObjectOperations`, full `StorageAPI` when the helper only needs `ObjectIO`,
`BucketOperations`, `ListOperations`, or `StorageAdminApi`. `ObjectOperations`, `BucketOperations`, `ListOperations`, or
`StorageAdminApi`.
- Acceptance: metadata helper contracts express the actual operation group - Acceptance: metadata helper contracts express the actual operation group
they need, while callers and persistence behavior remain unchanged. they need, while callers and persistence behavior remain unchanged.
- Must preserve: config/tier/rebalance serialized byte shapes, read/write
object names, legacy bucket/IAM migration normalization and skip behavior, - [~] `API-010` Narrow replication resync metadata bounds.
lock behavior around rebalance metadata merge, dynamic storage-class lookup, - Current branch slice: narrow replication resync status load/save/mark/persist
object APIs, scanner cache persistence, heal repair, replication helper bounds away from full `StorageAPI` when the helper only needs
persistence, and storage hot paths. `ObjectIO`.
- Acceptance: resync metadata helpers express object-I/O-only persistence
requirements, while replication execution, delete replication, multipart
replication, object lookups, and scheduling behavior remain on full
`StorageAPI` where needed.
- Must preserve: resync status serialization, resync metadata object paths,
in-memory status-map mutation order, stale-update rejection, periodic
persistence cadence, worker-token behavior, target replication decisions,
object replication, delete replication, multipart replication, scanner,
heal, and storage hot paths.
- Risk defense: do not move traits to `rustfs-storage-api`, do not remove - Risk defense: do not move traits to `rustfs-storage-api`, do not remove
`StorageAPI`, do not alter helper bodies or storage options, and keep `StorageAPI`, do not alter helper bodies or storage options, and do not
`save_rebalance_meta_with_merge` on full `StorageAPI` because it still needs narrow replication execution paths that use object/list/multipart/delete
`new_ns_lock`. operations beyond metadata persistence.
- Verification: focused compile/tests, migration guards, Rust risk scan, and - Verification: focused compile/tests, migration guards, and Rust risk scan
required quality/architecture, migration-preservation, and passed; required quality/architecture, migration-preservation, and
testing/verification review passed before push. testing/verification review is pending before push.
## Phase 8 Background Controller Tasks ## Phase 8 Background Controller Tasks
@@ -269,8 +279,8 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
## Next PRs ## Next PRs
1. `dependency-migration`: narrow metadata/helper bounds away from full 1. `dependency-migration`: narrow replication resync metadata helper bounds
`StorageAPI` where the helper only needs a specific operation trait. away from full `StorageAPI` where the helper only needs `ObjectIO`.
2. `api-extraction`: move only the pure server-config model into 2. `api-extraction`: move only the pure server-config model into
rustfs-config as CFG-003. rustfs-config as CFG-003.
3. `api-extraction`: keep the old rustfs_ecstore::config::* path with 3. `api-extraction`: keep the old rustfs_ecstore::config::* path with
@@ -286,9 +296,9 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
| Expert | Status | Notes | | Expert | Status | Notes |
|---|---|---| |---|---|---|
| Quality/architecture | pass | Confirmed the Rust diff only changes imports/generic bounds, the new operation-group bounds match actual calls, `StorageAPI` and `new_ns_lock` remain where needed, and no over-abstraction, naming regression, dependency reversal, or hot-path intrusion was found. | | Quality/architecture | pass | Confirmed the Rust diff only adds the `ObjectIO` import and narrows resync metadata load/save/mark/persist helper bounds; helper bodies are unchanged, broader replication execution paths remain on `StorageAPI`, and no new abstraction or crate split was added. |
| Migration preservation | pass | Confirmed config/tier/rebalance byte shapes, object names, buckets, options, bucket/IAM normalization and skip behavior, dynamic storage-class lookup, and rebalance metadata merge locking remain unchanged. | | Migration preservation | pass | Confirmed `read_config`/`save_config` already use the `ObjectIO` contract, while resync metadata serialization, object paths, storage options, status-map flow, and object/delete/multipart replication paths remain unchanged. |
| Testing/verification | pass | Confirmed the focused compile, config/tier/rebalance/bucket migration tests, migration guards, diff hygiene, and added-line Rust risk scan are sufficient; full pre-commit can be skipped under the current larger-granularity instruction. | | Testing/verification | pass | Confirmed the focused compile, replication/resync tests, migration guards, diff hygiene, and added-line risk scan are sufficient for this generic-bound-only slice, so full pre-commit can be skipped under the current larger-granularity instruction. |
## Verification Notes ## Verification Notes
@@ -297,41 +307,40 @@ Passed:
- `cargo check -p rustfs-ecstore`. - `cargo check -p rustfs-ecstore`.
- `cargo fmt --all --check`. - `cargo fmt --all --check`.
- `cargo check -p rustfs-storage-api -p rustfs-ecstore -p rustfs --lib`. - `cargo check -p rustfs-storage-api -p rustfs-ecstore -p rustfs --lib`.
- `cargo test -p rustfs-ecstore config --lib`; 59 passed. - `cargo test -p rustfs-ecstore replication --lib`; 58 passed.
- `cargo test -p rustfs-ecstore tier --lib`; 27 passed. - `cargo test -p rustfs-ecstore resync --lib`; 31 passed.
- `cargo test -p rustfs-ecstore rebalance --lib`; 198 passed.
- `cargo test -p rustfs-ecstore bucket::migration --lib`; 2 passed.
- `./scripts/check_architecture_migration_rules.sh`. - `./scripts/check_architecture_migration_rules.sh`.
- `./scripts/check_layer_dependencies.sh`. - `./scripts/check_layer_dependencies.sh`.
- `./scripts/check_metrics_migration_refs.sh`. - `./scripts/check_metrics_migration_refs.sh`.
- `./scripts/check_unsafe_code_allowances.sh`. - `./scripts/check_unsafe_code_allowances.sh`.
- `git diff --check`. - `git diff --check`.
- Rust code-quality scan on changed `.rs` files: broad full-file matches are - Rust code-quality scan on changed `.rs` files, plus added-line scan for
pre-existing test/business-code patterns; added-line scan found no new unwrap/expect, numeric casts, `Result<_, String>`, `Box<dyn Error>`,
unwrap/expect, numeric cast, `Result<_, String>`, `Box<dyn Error>`, println/eprintln, and `Ordering::Relaxed`; broad full-file matches are
println/eprintln, or `Ordering::Relaxed`. pre-existing touched-file patterns, and the added-line scan found no new
risky code patterns.
Notes: Notes:
- Full pre-commit is intentionally skipped when the focused tests and guards - Full pre-commit is intentionally skipped when the focused tests and guards
pass, per the current instruction to increase PR granularity. pass, per the current instruction to increase PR granularity.
- This slice changes generic bounds and imports only; helper bodies, storage - This slice changes generic bounds and imports only; helper bodies, storage
options, object names, and metadata normalization logic are unchanged. options, object paths, and resync serialization logic are unchanged.
- `save_rebalance_meta_with_merge` intentionally still requires full - Replication execution paths intentionally still require full `StorageAPI`
`StorageAPI` because it uses `new_ns_lock`. where they use object/list/multipart/delete operations.
- No temporary compatibility shim was added. - No temporary compatibility shim was added.
## Handoff Notes ## Handoff Notes
- Keep this API-009 slice as a `dependency-migration` PR that only narrows - Keep this API-010 slice as a `dependency-migration` PR that only narrows
metadata/helper generic bounds for config, tier, rebalance, and startup replication resync metadata helper generic bounds.
metadata migration helpers.
- Do not remove `StorageAPI` itself, object operation traits, or - Do not remove `StorageAPI` itself, object operation traits, or
`new_ns_lock` in this PR. `new_ns_lock` in this PR.
- Do not move traits into `rustfs-storage-api` or introduce new compatibility - Do not move traits into `rustfs-storage-api` or introduce new compatibility
shims in this PR. shims in this PR.
- Do not alter config/tier/rebalance serialized byte shapes, legacy bucket/IAM - Do not alter resync status serialization, metadata object paths, stale-update
migration normalization, object names, storage options, scanner cache writes, rejection, status-map mutation order, periodic persistence cadence, worker
heal object repair, object APIs, replication persistence, or storage hot-path token behavior, replication execution, delete replication, multipart
consumers in this PR. replication, scanner cache writes, heal object repair, object APIs, or storage
hot-path consumers in this PR.
- Do not add temporary compatibility code unless a matching - Do not add temporary compatibility code unless a matching
`RUSTFS_COMPAT_TODO(<task-id>)` marker and cleanup-register entry are added. `RUSTFS_COMPAT_TODO(<task-id>)` marker and cleanup-register entry are added.