mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-27 15:37:02 +00:00
refactor(scanner): narrow cache storage bounds (#3348)
This commit is contained in:
@@ -29,12 +29,11 @@ pub use rustfs_data_usage::{
|
|||||||
BucketTargetUsageInfo, BucketUsageInfo, DataUsageEntry, DataUsageHash, DataUsageHashMap, DataUsageInfo, hash_path,
|
BucketTargetUsageInfo, BucketUsageInfo, DataUsageEntry, DataUsageHash, DataUsageHashMap, DataUsageInfo, hash_path,
|
||||||
};
|
};
|
||||||
use rustfs_ecstore::{
|
use rustfs_ecstore::{
|
||||||
StorageAPI,
|
|
||||||
bucket::{lifecycle::lifecycle::TRANSITION_COMPLETE, replication::ReplicationConfig},
|
bucket::{lifecycle::lifecycle::TRANSITION_COMPLETE, replication::ReplicationConfig},
|
||||||
config::{com::save_config, storageclass},
|
config::{com::save_config, storageclass},
|
||||||
disk::{BUCKET_META_PREFIX, RUSTFS_META_BUCKET},
|
disk::{BUCKET_META_PREFIX, RUSTFS_META_BUCKET},
|
||||||
error::{Error, Result as StorageResult, StorageError},
|
error::{Error, Result as StorageResult, StorageError},
|
||||||
store_api::{ObjectInfo, ObjectOptions},
|
store_api::{ObjectIO, ObjectInfo, ObjectOptions},
|
||||||
};
|
};
|
||||||
use rustfs_utils::path::{SLASH_SEPARATOR, path_join_buf};
|
use rustfs_utils::path::{SLASH_SEPARATOR, path_join_buf};
|
||||||
use tokio::time::{Duration, Instant, sleep, timeout};
|
use tokio::time::{Duration, Instant, sleep, timeout};
|
||||||
@@ -613,7 +612,7 @@ impl DataUsageCache {
|
|||||||
/// Only backend errors are returned as errors.
|
/// Only backend errors are returned as errors.
|
||||||
/// The loader is optimistic and has no locking, but tries 5 times before giving up.
|
/// The loader is optimistic and has no locking, but tries 5 times before giving up.
|
||||||
/// If the object is not found, a nil error with empty data usage cache is returned.
|
/// If the object is not found, a nil error with empty data usage cache is returned.
|
||||||
pub async fn load<S: StorageAPI>(&mut self, store: Arc<S>, name: &str) -> StorageResult<()> {
|
pub async fn load<S: ObjectIO>(&mut self, store: Arc<S>, name: &str) -> StorageResult<()> {
|
||||||
// By default, empty data usage cache
|
// By default, empty data usage cache
|
||||||
*self = DataUsageCache::default();
|
*self = DataUsageCache::default();
|
||||||
|
|
||||||
@@ -659,7 +658,7 @@ impl DataUsageCache {
|
|||||||
}
|
}
|
||||||
// Inner load function that attempts to load from a specific path
|
// Inner load function that attempts to load from a specific path
|
||||||
// Returns (should_retry, cache_option, error_option)
|
// Returns (should_retry, cache_option, error_option)
|
||||||
async fn try_load_inner<S: StorageAPI>(
|
async fn try_load_inner<S: ObjectIO>(
|
||||||
store: Arc<S>,
|
store: Arc<S>,
|
||||||
load_name: &str,
|
load_name: &str,
|
||||||
timeout_duration: Duration,
|
timeout_duration: Duration,
|
||||||
@@ -854,7 +853,7 @@ impl DataUsageCache {
|
|||||||
Err(last_err.unwrap_or_else(|| StorageError::other("Failed to save data usage cache".to_string())))
|
Err(last_err.unwrap_or_else(|| StorageError::other("Failed to save data usage cache".to_string())))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_path_with_retry<S: StorageAPI>(
|
async fn save_path_with_retry<S: ObjectIO>(
|
||||||
store: Arc<S>,
|
store: Arc<S>,
|
||||||
path: &str,
|
path: &str,
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
@@ -877,7 +876,7 @@ impl DataUsageCache {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn save<S: StorageAPI>(&self, store: Arc<S>, name: &str) -> StorageResult<()> {
|
pub async fn save<S: ObjectIO>(&self, store: Arc<S>, name: &str) -> StorageResult<()> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
self.serialize(&mut rmp_serde::Serializer::new(&mut buf))?;
|
self.serialize(&mut rmp_serde::Serializer::new(&mut buf))?;
|
||||||
let timeout_duration = Self::cache_save_timeout();
|
let timeout_duration = Self::cache_save_timeout();
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ use rustfs_ecstore::error::{Error, StorageError};
|
|||||||
use rustfs_ecstore::global::GLOBAL_TierConfigMgr;
|
use rustfs_ecstore::global::GLOBAL_TierConfigMgr;
|
||||||
use rustfs_ecstore::new_object_layer_fn;
|
use rustfs_ecstore::new_object_layer_fn;
|
||||||
use rustfs_ecstore::set_disk::SetDisks;
|
use rustfs_ecstore::set_disk::SetDisks;
|
||||||
use rustfs_ecstore::store_api::{BucketInfo, BucketOperations, BucketOptions, ObjectInfo};
|
use rustfs_ecstore::store_api::{BucketInfo, BucketOperations, BucketOptions, ObjectIO, ObjectInfo};
|
||||||
use rustfs_ecstore::{StorageAPI, error::Result, store::ECStore};
|
use rustfs_ecstore::{error::Result, store::ECStore};
|
||||||
use rustfs_filemeta::FileMeta;
|
use rustfs_filemeta::FileMeta;
|
||||||
use rustfs_storage_api::{DiskSetSelector, StorageAdminApi};
|
use rustfs_storage_api::{DiskSetSelector, StorageAdminApi};
|
||||||
use rustfs_utils::path::path_join_buf;
|
use rustfs_utils::path::path_join_buf;
|
||||||
@@ -296,7 +296,7 @@ async fn send_cache_root_entry_info(
|
|||||||
bucket_result_tx.lock().await.send(cache_root_entry_info(cache)).await
|
bucket_result_tx.lock().await.send(cache_root_entry_info(cache)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn persist_and_publish_cache_snapshot<S: StorageAPI>(
|
async fn persist_and_publish_cache_snapshot<S: ObjectIO>(
|
||||||
store: Arc<S>,
|
store: Arc<S>,
|
||||||
updates: &mpsc::Sender<DataUsageCache>,
|
updates: &mpsc::Sender<DataUsageCache>,
|
||||||
cache_snapshot: DataUsageCache,
|
cache_snapshot: DataUsageCache,
|
||||||
|
|||||||
@@ -5,16 +5,15 @@ 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-replication-resync-bounds`
|
- Branch: `overtrue/arch-storage-api-helper-cleanup`
|
||||||
- Baseline: `origin/main` at `7191a3abae08918eedb117955280dc81e65450de`
|
- Baseline: `origin/main` at `2f7cc7cb9e5891b46db6e686c67636e9343762ce`
|
||||||
- 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 replication resync metadata helper generic bounds
|
- Rust code changes: narrow scanner data-usage cache load/save helper generic
|
||||||
away from full `StorageAPI` where helpers only need object I/O.
|
bounds away from full `StorageAPI` where helpers only need object I/O.
|
||||||
- CI/script changes: none.
|
- CI/script changes: none.
|
||||||
- Docs changes: record API-009 completion and the current replication resync
|
- Docs changes: record API-010 completion and the current scanner cache
|
||||||
metadata bound-narrowing context, verification evidence, and expert review
|
bound-narrowing context, verification evidence, and expert review outcomes.
|
||||||
outcomes.
|
|
||||||
|
|
||||||
## Phase 0 Tasks
|
## Phase 0 Tasks
|
||||||
|
|
||||||
@@ -235,23 +234,29 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
- 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.
|
||||||
|
|
||||||
- [~] `API-010` Narrow replication resync metadata bounds.
|
- [x] `API-010` Narrow replication resync metadata bounds.
|
||||||
- Current branch slice: narrow replication resync status load/save/mark/persist
|
- Completed slice: `rustfs/rustfs#3345` narrowed replication resync status
|
||||||
helper bounds away from full `StorageAPI` when the helper only needs
|
load/save/mark/persist helper bounds away from full `StorageAPI` when the
|
||||||
`ObjectIO`.
|
helper only needs `ObjectIO`.
|
||||||
- Acceptance: resync metadata helpers express object-I/O-only persistence
|
- Acceptance: resync metadata helpers express object-I/O-only persistence
|
||||||
requirements, while replication execution, delete replication, multipart
|
requirements, while replication execution, delete replication, multipart
|
||||||
replication, object lookups, and scheduling behavior remain on full
|
replication, object lookups, and scheduling behavior remain on full
|
||||||
`StorageAPI` where needed.
|
`StorageAPI` where needed.
|
||||||
- Must preserve: resync status serialization, resync metadata object paths,
|
|
||||||
in-memory status-map mutation order, stale-update rejection, periodic
|
- [~] `API-011` Narrow scanner cache helper storage bounds.
|
||||||
persistence cadence, worker-token behavior, target replication decisions,
|
- Current branch slice: narrow scanner data-usage cache load/save and cache
|
||||||
object replication, delete replication, multipart replication, scanner,
|
snapshot persistence helper bounds away from full `StorageAPI` when the
|
||||||
heal, and storage hot paths.
|
helper only needs `ObjectIO`.
|
||||||
|
- Acceptance: scanner cache persistence helpers express object-I/O-only
|
||||||
|
requirements, while scanner cycle orchestration, bucket scanning, local disk
|
||||||
|
selection, cache publication, and storage hot paths remain unchanged.
|
||||||
|
- Must preserve: data-usage cache wire format, cache object paths, backup
|
||||||
|
cache paths, retry and timeout behavior, cache-save metrics, publish/update
|
||||||
|
channel behavior, scanner cycle scheduling, disk scan concurrency, bucket
|
||||||
|
scan semantics, lifecycle/replication decisions, 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 do not
|
`StorageAPI`, do not alter helper bodies, and do not narrow scanner paths
|
||||||
narrow replication execution paths that use object/list/multipart/delete
|
that need bucket operations, disk inventory, or full storage orchestration.
|
||||||
operations beyond metadata persistence.
|
|
||||||
- Verification: focused compile/tests, migration guards, and Rust risk scan
|
- Verification: focused compile/tests, migration guards, and Rust risk scan
|
||||||
passed; required quality/architecture, migration-preservation, and
|
passed; required quality/architecture, migration-preservation, and
|
||||||
testing/verification review is pending before push.
|
testing/verification review is pending before push.
|
||||||
@@ -279,8 +284,8 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
|
|
||||||
## Next PRs
|
## Next PRs
|
||||||
|
|
||||||
1. `dependency-migration`: narrow replication resync metadata helper bounds
|
1. `dependency-migration`: narrow scanner data-usage cache helper bounds away
|
||||||
away from full `StorageAPI` where the helper only needs `ObjectIO`.
|
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
|
||||||
@@ -296,19 +301,18 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
|
|
||||||
| Expert | Status | Notes |
|
| Expert | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 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. |
|
| Quality/architecture | pass | Confirmed the Rust diff only narrows scanner cache helper bounds from `StorageAPI` to `ObjectIO`; helper bodies, scanner orchestration, bucket/disk/lifecycle/replication paths, and storage hot paths are 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. |
|
| Migration preservation | pass | Confirmed `ObjectIO` covers the actual `get_object_reader` and `put_object` calls, while cache wire format, object paths, backup behavior, retry/timeouts, metrics, publish/update flow, scanner scheduling, concurrency, and bucket scanning remain unchanged. |
|
||||||
| 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. |
|
| Testing/verification | pass | Confirmed the focused compile, `data_usage` and `scanner_io` 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
|
||||||
|
|
||||||
Passed:
|
Passed:
|
||||||
- `cargo fmt --all`.
|
- `cargo fmt --all`.
|
||||||
- `cargo check -p rustfs-ecstore`.
|
- `cargo check -p rustfs-scanner -p rustfs-ecstore -p rustfs --lib`.
|
||||||
- `cargo fmt --all --check`.
|
- `cargo fmt --all --check`.
|
||||||
- `cargo check -p rustfs-storage-api -p rustfs-ecstore -p rustfs --lib`.
|
- `cargo test -p rustfs-scanner data_usage --lib`; 21 passed.
|
||||||
- `cargo test -p rustfs-ecstore replication --lib`; 58 passed.
|
- `cargo test -p rustfs-scanner scanner_io --lib`; 18 passed.
|
||||||
- `cargo test -p rustfs-ecstore resync --lib`; 31 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`.
|
||||||
@@ -323,24 +327,25 @@ Passed:
|
|||||||
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, cache
|
||||||
options, object paths, and resync serialization logic are unchanged.
|
object paths, backup paths, retry/timeout behavior, metrics, and publish
|
||||||
- Replication execution paths intentionally still require full `StorageAPI`
|
logic are unchanged.
|
||||||
where they use object/list/multipart/delete operations.
|
- Scanner orchestration paths intentionally still require full `StorageAPI`
|
||||||
|
where they use bucket operations, disk inventory, or broader storage
|
||||||
|
orchestration.
|
||||||
- No temporary compatibility shim was added.
|
- No temporary compatibility shim was added.
|
||||||
|
|
||||||
## Handoff Notes
|
## Handoff Notes
|
||||||
|
|
||||||
- Keep this API-010 slice as a `dependency-migration` PR that only narrows
|
- Keep this API-011 slice as a `dependency-migration` PR that only narrows
|
||||||
replication resync metadata helper generic bounds.
|
scanner data-usage cache helper generic bounds.
|
||||||
- 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 resync status serialization, metadata object paths, stale-update
|
- Do not alter data-usage cache wire format, cache object paths, backup paths,
|
||||||
rejection, status-map mutation order, periodic persistence cadence, worker
|
retry/timeout behavior, metrics, update publication, scanner cycle
|
||||||
token behavior, replication execution, delete replication, multipart
|
orchestration, bucket scanning, disk scan concurrency, heal object repair,
|
||||||
replication, scanner cache writes, heal object repair, object APIs, or storage
|
object APIs, or storage hot-path consumers in this PR.
|
||||||
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user