refactor: use relative local compat consumers (#3723)

This commit is contained in:
安正超
2026-06-22 13:22:48 +08:00
committed by GitHub
parent 2f25cf606e
commit da08e411f1
10 changed files with 159 additions and 125 deletions
+35 -10
View File
@@ -5,16 +5,17 @@ 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-root-compat-relative-consumers` - Branch: `overtrue/arch-rustfs-local-compat-consumers`
- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109`. - Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110`.
- Based on: API-108 slice. - Based on: API-109 slice.
- PR type for this branch: `pure-move` - PR type for this branch: `pure-move`
- Runtime behavior changes: none. - Runtime behavior changes: none.
- Rust code changes: collapse crate-qualified root compatibility and storage - Rust code changes: collapse crate-qualified RustFS app/admin/storage local
owner compatibility consumer paths into relative `super::`/`self::` paths. compatibility consumer paths into relative `super::`/`super::super::` paths.
- CI/script changes: guard selected RustFS root and storage owner consumers - CI/script changes: guard selected RustFS app/admin/storage local consumers
against crate-qualified compatibility paths. against crate-qualified compatibility paths.
- Docs changes: record the API-109 relative compatibility consumer cleanup. - Docs changes: record the API-110 relative local compatibility consumer
cleanup.
## Phase 0 Tasks ## Phase 0 Tasks
@@ -558,6 +559,18 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
compatibility consumer residual scans, migration and layer guards, compatibility consumer residual scans, migration and layer guards,
formatting, diff hygiene, Rust risk scan, pre-commit quality gate, and formatting, diff hygiene, Rust risk scan, pre-commit quality gate, and
three-expert review. three-expert review.
- [x] `API-110` Collapse RustFS local compatibility consumer paths.
- Completed slice: replace crate-qualified app usecase, admin router, and
storage ECFS test compatibility consumers with relative owner paths.
- Acceptance: selected RustFS app/admin/storage consumers no longer point back
to local compatibility facades through crate-qualified paths; migration
rules reject regressions.
- Must preserve: app object/bucket/multipart/admin usecase behavior,
lifecycle transition and capacity tests, admin replication/router helpers,
and storage ECFS test coverage.
- Verification: RustFS test-target compile coverage, local compatibility
consumer residual scan, migration and layer guards, formatting, diff
hygiene, Rust risk scan, pre-commit quality gate, and three-expert review.
- [x] `G-012` Inventory placement and repair invariants. - [x] `G-012` Inventory placement and repair invariants.
- Acceptance: - Acceptance:
[`placement-repair-invariants.md`](placement-repair-invariants.md) records [`placement-repair-invariants.md`](placement-repair-invariants.md) records
@@ -3591,14 +3604,26 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
| Expert | Status | Notes | | Expert | Status | Notes |
|---|---|---| |---|---|---|
| Quality/architecture | pass | API-109 keeps selected root and storage owner compatibility consumers owner-relative by replacing crate-qualified compatibility paths with scoped `super::` or `self::` paths. | | Quality/architecture | pass | API-110 keeps selected app/admin/storage local compatibility consumers owner-relative by replacing crate-qualified compatibility paths with scoped `super::` or `super::super::` paths. |
| Migration preservation | pass | The new guards reject crate-qualified root compatibility and storage owner compatibility consumer paths while preserving the same local facade names and aliases. | | Migration preservation | pass | The new guard rejects crate-qualified app/admin/storage local compatibility consumer paths while preserving the same facade names and aliases. |
| Testing/verification | pass | Focused compile, root/storage owner residual scans, migration guard, layer guard, formatting, diff hygiene, risk scan, and full pre-commit passed. | | Testing/verification | pass | Focused compile, local compatibility consumer residual scan, migration guard, layer guard, formatting, diff hygiene, risk scan, and full pre-commit passed. |
## Verification Notes ## Verification Notes
Passed before push: Passed before push:
- Issue #660 API-110 current slice:
- `cargo check -p rustfs --tests`: passed.
- `cargo fmt --all`: passed.
- `cargo fmt --all --check`: passed.
- `git diff --check`: passed.
- `bash -n scripts/check_architecture_migration_rules.sh`: passed.
- `./scripts/check_architecture_migration_rules.sh`: passed.
- `./scripts/check_layer_dependencies.sh`: passed.
- RustFS local compatibility consumer residual scan: passed.
- Rust risk scan on changed Rust files and guard script: passed.
- `make pre-commit`: passed.
- Issue #660 API-109 current slice: - Issue #660 API-109 current slice:
- `cargo check -p rustfs --tests`: passed. - `cargo check -p rustfs --tests`: passed.
- `cargo fmt --all`: passed. - `cargo fmt --all`: passed.
+27 -29
View File
@@ -12,25 +12,25 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::admin::console::{is_console_path, make_console_server}; use super::router_storage_compat::GLOBAL_BOOT_TIME;
use crate::admin::handlers::oidc::is_oidc_path; use super::router_storage_compat::PeerRestClient;
use crate::admin::router_storage_compat::GLOBAL_BOOT_TIME; use super::router_storage_compat::bandwidth::monitor::BandwidthDetails;
use crate::admin::router_storage_compat::PeerRestClient; use super::router_storage_compat::bucket_target_sys::{
use crate::admin::router_storage_compat::bandwidth::monitor::BandwidthDetails;
use crate::admin::router_storage_compat::bucket_target_sys::{
BucketTargetSys, PutObjectOptions, RemoveObjectOptions, S3ClientError, TargetClient, BucketTargetSys, PutObjectOptions, RemoveObjectOptions, S3ClientError, TargetClient,
}; };
use crate::admin::router_storage_compat::get_global_notification_sys; use super::router_storage_compat::get_global_notification_sys;
use crate::admin::router_storage_compat::metadata::BUCKET_TARGETS_FILE; use super::router_storage_compat::metadata::BUCKET_TARGETS_FILE;
use crate::admin::router_storage_compat::metadata_sys; use super::router_storage_compat::metadata_sys;
use crate::admin::router_storage_compat::read_admin_config_without_migrate; use super::router_storage_compat::read_admin_config_without_migrate;
use crate::admin::router_storage_compat::replication::{ use super::router_storage_compat::replication::{
BucketReplicationResyncStatus, BucketStats, GLOBAL_REPLICATION_STATS, ObjectOpts, ResyncOpts, get_global_replication_pool, BucketReplicationResyncStatus, BucketStats, GLOBAL_REPLICATION_STATS, ObjectOpts, ResyncOpts, get_global_replication_pool,
}; };
use crate::admin::router_storage_compat::target::{BucketTarget, BucketTargetType, BucketTargets}; use super::router_storage_compat::target::{BucketTarget, BucketTargetType, BucketTargets};
use crate::admin::router_storage_compat::versioning_sys::BucketVersioningSys; use super::router_storage_compat::versioning_sys::BucketVersioningSys;
use crate::admin::router_storage_compat::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _}; use super::router_storage_compat::{AdminReplicationConfigExt as _, AdminVersioningConfigExt as _};
use crate::admin::router_storage_compat::{get_global_bucket_monitor, get_global_deployment_id, get_global_region}; use super::router_storage_compat::{get_global_bucket_monitor, get_global_deployment_id, get_global_region};
use crate::admin::console::{is_console_path, make_console_server};
use crate::admin::handlers::oidc::is_oidc_path;
use crate::app::context::resolve_object_store_handle; use crate::app::context::resolve_object_store_handle;
use crate::app::object_usecase::DefaultObjectUsecase; use crate::app::object_usecase::DefaultObjectUsecase;
use crate::auth::{check_key_valid, get_session_token}; use crate::auth::{check_key_valid, get_session_token};
@@ -1419,9 +1419,7 @@ async fn ensure_replication_bucket_exists(bucket: &str) -> S3Result<()> {
async fn ensure_replication_config_exists(bucket: &str) -> S3Result<()> { async fn ensure_replication_config_exists(bucket: &str) -> S3Result<()> {
match metadata_sys::get_replication_config(bucket).await { match metadata_sys::get_replication_config(bucket).await {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(crate::admin::router_storage_compat::StorageError::ConfigNotFound) => { Err(super::router_storage_compat::StorageError::ConfigNotFound) => Err(s3_error!(ReplicationConfigurationNotFoundError)),
Err(s3_error!(ReplicationConfigurationNotFoundError))
}
Err(err) => Err(ApiError::from(err).into()), Err(err) => Err(ApiError::from(err).into()),
} }
} }
@@ -1946,7 +1944,7 @@ async fn resolve_replication_target_client(bucket: &str, target: &BucketTarget)
fn build_replication_probe_put_options(now: OffsetDateTime) -> PutObjectOptions { fn build_replication_probe_put_options(now: OffsetDateTime) -> PutObjectOptions {
PutObjectOptions { PutObjectOptions {
internal: crate::admin::router_storage_compat::bucket_target_sys::AdvancedPutOptions { internal: super::router_storage_compat::bucket_target_sys::AdvancedPutOptions {
source_version_id: Uuid::new_v4().to_string(), source_version_id: Uuid::new_v4().to_string(),
replication_status: ReplicationStatusType::Replica, replication_status: ReplicationStatusType::Replica,
source_mtime: now, source_mtime: now,
@@ -2061,7 +2059,7 @@ async fn source_bucket_requires_object_lock(bucket: &str) -> S3Result<bool> {
.object_lock_enabled .object_lock_enabled
.as_ref() .as_ref()
.is_some_and(|state| state.as_str() == s3s::dto::ObjectLockEnabled::ENABLED)), .is_some_and(|state| state.as_str() == s3s::dto::ObjectLockEnabled::ENABLED)),
Err(crate::admin::router_storage_compat::StorageError::ConfigNotFound) => Ok(false), Err(super::router_storage_compat::StorageError::ConfigNotFound) => Ok(false),
Err(err) => Err(ApiError::from(err).into()), Err(err) => Err(ApiError::from(err).into()),
} }
} }
@@ -2775,7 +2773,7 @@ mod tests {
#[test] #[test]
fn apply_replication_reset_to_targets_updates_matching_target() { fn apply_replication_reset_to_targets_updates_matching_target() {
let mut targets = BucketTargets { let mut targets = BucketTargets {
targets: vec![crate::admin::router_storage_compat::target::BucketTarget { targets: vec![super::super::router_storage_compat::target::BucketTarget {
arn: "arn:target".to_string(), arn: "arn:target".to_string(),
..Default::default() ..Default::default()
}], }],
@@ -2797,10 +2795,10 @@ mod tests {
let mut status = BucketReplicationResyncStatus::new(); let mut status = BucketReplicationResyncStatus::new();
status.targets_map.insert( status.targets_map.insert(
"arn:z".to_string(), "arn:z".to_string(),
crate::admin::router_storage_compat::replication::TargetReplicationResyncStatus { super::super::router_storage_compat::replication::TargetReplicationResyncStatus {
resync_id: "rid-z".to_string(), resync_id: "rid-z".to_string(),
last_update: Some(datetime!(2025-01-03 00:00 UTC)), last_update: Some(datetime!(2025-01-03 00:00 UTC)),
resync_status: crate::admin::router_storage_compat::replication::ResyncStatusType::ResyncFailed, resync_status: super::super::router_storage_compat::replication::ResyncStatusType::ResyncFailed,
failed_count: 2, failed_count: 2,
failed_size: 4, failed_size: 4,
bucket: "bucket-z".to_string(), bucket: "bucket-z".to_string(),
@@ -2810,10 +2808,10 @@ mod tests {
); );
status.targets_map.insert( status.targets_map.insert(
"arn:a".to_string(), "arn:a".to_string(),
crate::admin::router_storage_compat::replication::TargetReplicationResyncStatus { super::super::router_storage_compat::replication::TargetReplicationResyncStatus {
resync_id: "rid-a".to_string(), resync_id: "rid-a".to_string(),
last_update: Some(datetime!(2025-01-02 00:00 UTC)), last_update: Some(datetime!(2025-01-02 00:00 UTC)),
resync_status: crate::admin::router_storage_compat::replication::ResyncStatusType::ResyncCompleted, resync_status: super::super::router_storage_compat::replication::ResyncStatusType::ResyncCompleted,
replicated_count: 3, replicated_count: 3,
replicated_size: 9, replicated_size: 9,
bucket: "bucket-a".to_string(), bucket: "bucket-a".to_string(),
@@ -2843,10 +2841,10 @@ mod tests {
let mut status = BucketReplicationResyncStatus::new(); let mut status = BucketReplicationResyncStatus::new();
status.targets_map.insert( status.targets_map.insert(
"arn:z".to_string(), "arn:z".to_string(),
crate::admin::router_storage_compat::replication::TargetReplicationResyncStatus { super::super::router_storage_compat::replication::TargetReplicationResyncStatus {
resync_id: "rid-z".to_string(), resync_id: "rid-z".to_string(),
last_update: Some(datetime!(2025-02-03 00:00 UTC)), last_update: Some(datetime!(2025-02-03 00:00 UTC)),
resync_status: crate::admin::router_storage_compat::replication::ResyncStatusType::ResyncFailed, resync_status: super::super::router_storage_compat::replication::ResyncStatusType::ResyncFailed,
failed_count: 2, failed_count: 2,
failed_size: 4, failed_size: 4,
bucket: "bucket-z".to_string(), bucket: "bucket-z".to_string(),
@@ -2856,10 +2854,10 @@ mod tests {
); );
status.targets_map.insert( status.targets_map.insert(
"arn:a".to_string(), "arn:a".to_string(),
crate::admin::router_storage_compat::replication::TargetReplicationResyncStatus { super::super::router_storage_compat::replication::TargetReplicationResyncStatus {
resync_id: "rid-a".to_string(), resync_id: "rid-a".to_string(),
last_update: Some(datetime!(2025-02-02 00:00 UTC)), last_update: Some(datetime!(2025-02-02 00:00 UTC)),
resync_status: crate::admin::router_storage_compat::replication::ResyncStatusType::ResyncCompleted, resync_status: super::super::router_storage_compat::replication::ResyncStatusType::ResyncCompleted,
replicated_count: 3, replicated_count: 3,
replicated_size: 9, replicated_size: 9,
bucket: "bucket-a".to_string(), bucket: "bucket-a".to_string(),
+7 -7
View File
@@ -14,14 +14,14 @@
//! Admin application use-case contracts. //! Admin application use-case contracts.
use crate::app::context::{AppContext, get_global_app_context, resolve_object_store_handle_for_context}; use super::usecase_storage_compat::ECStore;
use crate::app::usecase_storage_compat::ECStore; use super::usecase_storage_compat::EndpointServerPools;
use crate::app::usecase_storage_compat::EndpointServerPools; use super::usecase_storage_compat::get_server_info;
use crate::app::usecase_storage_compat::get_server_info; use super::usecase_storage_compat::{
use crate::app::usecase_storage_compat::{
PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free, PoolDecommissionInfo, PoolStatus, get_total_usable_capacity, get_total_usable_capacity_free,
}; };
use crate::app::usecase_storage_compat::{apply_bucket_usage_memory_overlay, load_data_usage_from_backend}; use super::usecase_storage_compat::{apply_bucket_usage_memory_overlay, load_data_usage_from_backend};
use crate::app::context::{AppContext, get_global_app_context, resolve_object_store_handle_for_context};
use crate::capacity::resolve_admin_used_capacity; use crate::capacity::resolve_admin_used_capacity;
use crate::error::ApiError; use crate::error::ApiError;
use crate::server::{DependencyReadiness, collect_dependency_readiness as collect_runtime_dependency_readiness}; use crate::server::{DependencyReadiness, collect_dependency_readiness as collect_runtime_dependency_readiness};
@@ -403,8 +403,8 @@ impl DefaultAdminUsecase {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::super::usecase_storage_compat::{PoolDecommissionInfo, PoolStatus};
use super::*; use super::*;
use crate::app::usecase_storage_compat::{PoolDecommissionInfo, PoolStatus};
use time::OffsetDateTime; use time::OffsetDateTime;
#[tokio::test] #[tokio::test]
+13 -13
View File
@@ -14,18 +14,12 @@
//! Bucket application use-case contracts. //! Bucket application use-case contracts.
use crate::admin::handlers::site_replication::{ use super::usecase_storage_compat::ECStore;
site_replication_bucket_meta_hook, site_replication_delete_bucket_hook, site_replication_make_bucket_hook, use super::usecase_storage_compat::StorageError;
}; use super::usecase_storage_compat::get_global_notification_sys;
use crate::app::context::{ use super::usecase_storage_compat::object_api_utils::to_s3s_etag;
AppContext, default_notify_interface, get_global_app_context, resolve_object_store_handle_for_context, use super::usecase_storage_compat::{AppObjectLockConfigExt as _, AppVersioningConfigExt as _};
}; use super::usecase_storage_compat::{
use crate::app::usecase_storage_compat::ECStore;
use crate::app::usecase_storage_compat::StorageError;
use crate::app::usecase_storage_compat::get_global_notification_sys;
use crate::app::usecase_storage_compat::object_api_utils::to_s3s_etag;
use crate::app::usecase_storage_compat::{AppObjectLockConfigExt as _, AppVersioningConfigExt as _};
use crate::app::usecase_storage_compat::{
bucket_target_sys::BucketTargetSys, bucket_target_sys::BucketTargetSys,
lifecycle::bucket_lifecycle_ops::{ lifecycle::bucket_lifecycle_ops::{
enqueue_expiry_for_existing_objects, enqueue_transition_for_existing_objects, validate_lifecycle_config, enqueue_expiry_for_existing_objects, enqueue_transition_for_existing_objects, validate_lifecycle_config,
@@ -42,6 +36,12 @@ use crate::app::usecase_storage_compat::{
utils::serialize, utils::serialize,
versioning_sys::BucketVersioningSys, versioning_sys::BucketVersioningSys,
}; };
use crate::admin::handlers::site_replication::{
site_replication_bucket_meta_hook, site_replication_delete_bucket_hook, site_replication_make_bucket_hook,
};
use crate::app::context::{
AppContext, default_notify_interface, get_global_app_context, resolve_object_store_handle_for_context,
};
use crate::auth::get_condition_values_with_client_info; use crate::auth::get_condition_values_with_client_info;
use crate::error::ApiError; use crate::error::ApiError;
use crate::server::RemoteAddr; use crate::server::RemoteAddr;
@@ -2285,7 +2285,7 @@ mod tests {
BucketTargets { BucketTargets {
targets: arns targets: arns
.iter() .iter()
.map(|arn| crate::app::usecase_storage_compat::target::BucketTarget { .map(|arn| super::super::usecase_storage_compat::target::BucketTarget {
arn: (*arn).to_string(), arn: (*arn).to_string(),
target_type: BucketTargetType::ReplicationService, target_type: BucketTargetType::ReplicationService,
..Default::default() ..Default::default()
+2 -2
View File
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use crate::app::usecase_storage_compat::{ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints, metadata_sys}; use super::usecase_storage_compat::{ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints, metadata_sys};
use rustfs_common::heal_channel::{HealOpts, HealScanMode}; use rustfs_common::heal_channel::{HealOpts, HealScanMode};
use rustfs_object_capacity::capacity_manager::{HybridStrategyConfig, create_isolated_manager}; use rustfs_object_capacity::capacity_manager::{HybridStrategyConfig, create_isolated_manager};
use rustfs_storage_api::{BucketOperations, BucketOptions, HealOperations as _, MakeBucketOptions, ObjectIO as _}; use rustfs_storage_api::{BucketOperations, BucketOptions, HealOperations as _, MakeBucketOptions, ObjectIO as _};
@@ -77,7 +77,7 @@ async fn setup_capacity_dirty_scope_env() -> (Vec<PathBuf>, Arc<ECStore>) {
}; };
let endpoint_pools = EndpointServerPools(vec![pool_endpoints]); let endpoint_pools = EndpointServerPools(vec![pool_endpoints]);
crate::app::usecase_storage_compat::init_local_disks(endpoint_pools.clone()) super::usecase_storage_compat::init_local_disks(endpoint_pools.clone())
.await .await
.unwrap(); .unwrap();
@@ -12,9 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use super::{multipart_usecase::DefaultMultipartUsecase, object_usecase::DefaultObjectUsecase}; use super::usecase_storage_compat::{
use crate::app::bucket_usecase::DefaultBucketUsecase;
use crate::app::usecase_storage_compat::{
AppWarmBackend, ECStore, Endpoint, EndpointServerPools, Endpoints, GLOBAL_TierConfigMgr, PoolEndpoints, TierConfig, TierType, AppWarmBackend, ECStore, Endpoint, EndpointServerPools, Endpoints, GLOBAL_TierConfigMgr, PoolEndpoints, TierConfig, TierType,
WarmBackendGetOpts, WarmBackendGetOpts,
metadata::{BUCKET_LIFECYCLE_CONFIG, OBJECT_LOCK_CONFIG}, metadata::{BUCKET_LIFECYCLE_CONFIG, OBJECT_LOCK_CONFIG},
@@ -22,6 +20,8 @@ use crate::app::usecase_storage_compat::{
object_api_utils::to_s3s_etag, object_api_utils::to_s3s_etag,
transition_api::{ReadCloser, ReaderImpl}, transition_api::{ReadCloser, ReaderImpl},
}; };
use super::{multipart_usecase::DefaultMultipartUsecase, object_usecase::DefaultObjectUsecase};
use crate::app::bucket_usecase::DefaultBucketUsecase;
use crate::storage::ecfs::FS; use crate::storage::ecfs::FS;
use crate::storage::{ use crate::storage::{
StorageObjectInfo as ObjectInfo, StorageObjectOptions as ObjectOptions, StoragePutObjReader as PutObjReader, StorageObjectInfo as ObjectInfo, StorageObjectOptions as ObjectOptions, StoragePutObjReader as PutObjReader,
@@ -107,7 +107,7 @@ async fn setup_test_env() -> (Vec<PathBuf>, Arc<ECStore>) {
let endpoint_pools = EndpointServerPools(vec![pool_endpoints]); let endpoint_pools = EndpointServerPools(vec![pool_endpoints]);
crate::app::usecase_storage_compat::init_local_disks(endpoint_pools.clone()) super::usecase_storage_compat::init_local_disks(endpoint_pools.clone())
.await .await
.unwrap(); .unwrap();
@@ -126,7 +126,7 @@ async fn setup_test_env() -> (Vec<PathBuf>, Arc<ECStore>) {
let buckets = buckets_list.into_iter().map(|v| v.name).collect(); let buckets = buckets_list.into_iter().map(|v| v.name).collect();
metadata_sys::init_bucket_metadata_sys(ecstore.clone(), buckets).await; metadata_sys::init_bucket_metadata_sys(ecstore.clone(), buckets).await;
crate::app::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::init_background_expiry(ecstore.clone()).await; super::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::init_background_expiry(ecstore.clone()).await;
let _ = GLOBAL_ENV.set((disk_paths.clone(), ecstore.clone())); let _ = GLOBAL_ENV.set((disk_paths.clone(), ecstore.clone()));
@@ -926,7 +926,7 @@ async fn delete_transitioned_object_removes_remote_tier_copy_via_usecase() {
.expect("Failed to set lifecycle configuration"); .expect("Failed to set lifecycle configuration");
let _ = upload_test_object(&ecstore, bucket.as_str(), object, payload).await; let _ = upload_test_object(&ecstore, bucket.as_str(), object, payload).await;
crate::app::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::enqueue_transition_for_existing_objects( super::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::enqueue_transition_for_existing_objects(
ecstore.clone(), ecstore.clone(),
bucket.as_str(), bucket.as_str(),
) )
@@ -986,7 +986,7 @@ async fn lifecycle_transition_marks_dirty_disks_for_capacity_manager() {
.expect("Failed to set lifecycle configuration"); .expect("Failed to set lifecycle configuration");
let _ = upload_test_object(&ecstore, bucket.as_str(), object, payload).await; let _ = upload_test_object(&ecstore, bucket.as_str(), object, payload).await;
crate::app::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::enqueue_transition_for_existing_objects( super::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::enqueue_transition_for_existing_objects(
ecstore.clone(), ecstore.clone(),
bucket.as_str(), bucket.as_str(),
) )
+21 -27
View File
@@ -14,24 +14,24 @@
//! Multipart application use-case contracts. //! Multipart application use-case contracts.
use crate::app::context::{AppContext, get_global_app_context, resolve_object_store_handle_for_context}; use super::usecase_storage_compat::ECStore;
use crate::app::object_usecase::{build_put_like_object_lock_metadata, validate_existing_object_lock_for_write}; use super::usecase_storage_compat::is_disk_compressible;
use crate::app::usecase_storage_compat::ECStore; use super::usecase_storage_compat::is_valid_storage_class;
use crate::app::usecase_storage_compat::is_disk_compressible; use super::usecase_storage_compat::object_api_utils::to_s3s_etag;
use crate::app::usecase_storage_compat::is_valid_storage_class; use super::usecase_storage_compat::quota::checker::QuotaChecker;
use crate::app::usecase_storage_compat::object_api_utils::to_s3s_etag;
use crate::app::usecase_storage_compat::quota::checker::QuotaChecker;
#[cfg(test)] #[cfg(test)]
use crate::app::usecase_storage_compat::{DecryptReader, EncryptReader, HardLimitReader, boxed_reader, wrap_reader}; use super::usecase_storage_compat::{DecryptReader, EncryptReader, HardLimitReader, boxed_reader, wrap_reader};
use crate::app::usecase_storage_compat::{HashReader, WritePlan}; use super::usecase_storage_compat::{HashReader, WritePlan};
use crate::app::usecase_storage_compat::{StorageError, is_err_object_not_found, is_err_version_not_found}; use super::usecase_storage_compat::{StorageError, is_err_object_not_found, is_err_version_not_found};
use crate::app::usecase_storage_compat::{ use super::usecase_storage_compat::{
lifecycle::{bucket_lifecycle_audit::LcEventSrc, bucket_lifecycle_ops::enqueue_transition_immediate}, lifecycle::{bucket_lifecycle_audit::LcEventSrc, bucket_lifecycle_ops::enqueue_transition_immediate},
metadata_sys, metadata_sys,
quota::QuotaOperation, quota::QuotaOperation,
replication::{get_must_replicate_options, must_replicate, schedule_replication}, replication::{get_must_replicate_options, must_replicate, schedule_replication},
versioning_sys::BucketVersioningSys, versioning_sys::BucketVersioningSys,
}; };
use crate::app::context::{AppContext, get_global_app_context, resolve_object_store_handle_for_context};
use crate::app::object_usecase::{build_put_like_object_lock_metadata, validate_existing_object_lock_for_write};
use crate::capacity::record_capacity_write; use crate::capacity::record_capacity_write;
use crate::error::ApiError; use crate::error::ApiError;
use crate::storage::access::has_bypass_governance_header; use crate::storage::access::has_bypass_governance_header;
@@ -482,7 +482,7 @@ impl DefaultMultipartUsecase {
)); ));
} }
// Update quota tracking after successful multipart upload // Update quota tracking after successful multipart upload
crate::app::usecase_storage_compat::record_bucket_object_write_memory( super::usecase_storage_compat::record_bucket_object_write_memory(
&bucket, &bucket,
previous_current_size, previous_current_size,
obj_info.size.max(0) as u64, obj_info.size.max(0) as u64,
@@ -675,7 +675,7 @@ impl DefaultMultipartUsecase {
rustfs_utils::http::insert_str( rustfs_utils::http::insert_str(
&mut metadata, &mut metadata,
rustfs_utils::http::SUFFIX_COMPRESSION, rustfs_utils::http::SUFFIX_COMPRESSION,
crate::app::usecase_storage_compat::compression_metadata_value(CompressionAlgorithm::default()), super::usecase_storage_compat::compression_metadata_value(CompressionAlgorithm::default()),
); );
} }
@@ -894,12 +894,9 @@ impl DefaultMultipartUsecase {
.ok_or_else(|| ApiError::from(StorageError::other("Missing SSE-C session material")))?; .ok_or_else(|| ApiError::from(StorageError::other("Missing SSE-C session material")))?;
let ssec_write = match ssec_material.key_kind { let ssec_write = match ssec_material.key_kind {
crate::storage::sse::EncryptionKeyKind::Object => { crate::storage::sse::EncryptionKeyKind::Object => {
crate::app::usecase_storage_compat::WriteEncryption::multipart_object_key( super::usecase_storage_compat::WriteEncryption::multipart_object_key(ssec_material.key_bytes, part_id as u32)
ssec_material.key_bytes,
part_id as u32,
)
} }
crate::storage::sse::EncryptionKeyKind::Direct => crate::app::usecase_storage_compat::WriteEncryption::multipart( crate::storage::sse::EncryptionKeyKind::Direct => super::usecase_storage_compat::WriteEncryption::multipart(
ssec_material.key_bytes, ssec_material.key_bytes,
ssec_material.base_nonce, ssec_material.base_nonce,
part_id, part_id,
@@ -919,12 +916,12 @@ impl DefaultMultipartUsecase {
.ok_or_else(|| ApiError::from(StorageError::other("Missing managed SSE session material")))?; .ok_or_else(|| ApiError::from(StorageError::other("Missing managed SSE session material")))?;
let managed_write = match managed_material.key_kind { let managed_write = match managed_material.key_kind {
crate::storage::sse::EncryptionKeyKind::Object => { crate::storage::sse::EncryptionKeyKind::Object => {
crate::app::usecase_storage_compat::WriteEncryption::multipart_object_key( super::usecase_storage_compat::WriteEncryption::multipart_object_key(
managed_material.key_bytes, managed_material.key_bytes,
part_id as u32, part_id as u32,
) )
} }
crate::storage::sse::EncryptionKeyKind::Direct => crate::app::usecase_storage_compat::WriteEncryption::multipart( crate::storage::sse::EncryptionKeyKind::Direct => super::usecase_storage_compat::WriteEncryption::multipart(
managed_material.key_bytes, managed_material.key_bytes,
managed_material.base_nonce, managed_material.base_nonce,
part_id, part_id,
@@ -1243,12 +1240,9 @@ impl DefaultMultipartUsecase {
.ok_or_else(|| ApiError::from(StorageError::other("Missing SSE-C session material")))?; .ok_or_else(|| ApiError::from(StorageError::other("Missing SSE-C session material")))?;
let ssec_write = match ssec_material.key_kind { let ssec_write = match ssec_material.key_kind {
crate::storage::sse::EncryptionKeyKind::Object => { crate::storage::sse::EncryptionKeyKind::Object => {
crate::app::usecase_storage_compat::WriteEncryption::multipart_object_key( super::usecase_storage_compat::WriteEncryption::multipart_object_key(ssec_material.key_bytes, part_id as u32)
ssec_material.key_bytes,
part_id as u32,
)
} }
crate::storage::sse::EncryptionKeyKind::Direct => crate::app::usecase_storage_compat::WriteEncryption::multipart( crate::storage::sse::EncryptionKeyKind::Direct => super::usecase_storage_compat::WriteEncryption::multipart(
ssec_material.key_bytes, ssec_material.key_bytes,
ssec_material.base_nonce, ssec_material.base_nonce,
part_id, part_id,
@@ -1272,12 +1266,12 @@ impl DefaultMultipartUsecase {
.ok_or_else(|| ApiError::from(StorageError::other("Missing managed SSE session material")))?; .ok_or_else(|| ApiError::from(StorageError::other("Missing managed SSE session material")))?;
let managed_write = match managed_material.key_kind { let managed_write = match managed_material.key_kind {
crate::storage::sse::EncryptionKeyKind::Object => { crate::storage::sse::EncryptionKeyKind::Object => {
crate::app::usecase_storage_compat::WriteEncryption::multipart_object_key( super::usecase_storage_compat::WriteEncryption::multipart_object_key(
managed_material.key_bytes, managed_material.key_bytes,
part_id as u32, part_id as u32,
) )
} }
crate::storage::sse::EncryptionKeyKind::Direct => crate::app::usecase_storage_compat::WriteEncryption::multipart( crate::storage::sse::EncryptionKeyKind::Direct => super::usecase_storage_compat::WriteEncryption::multipart(
managed_material.key_bytes, managed_material.key_bytes,
managed_material.base_nonce, managed_material.base_nonce,
part_id, part_id,
+24 -24
View File
@@ -48,21 +48,21 @@ use metrics::{counter, histogram};
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
use rustfs_object_capacity::capacity_manager::get_capacity_manager; use rustfs_object_capacity::capacity_manager::get_capacity_manager;
// Performance metrics recording (with zero-copy-metrics integration) // Performance metrics recording (with zero-copy-metrics integration)
use crate::app::usecase_storage_compat::ECStore; use super::usecase_storage_compat::ECStore;
use crate::app::usecase_storage_compat::object_api_utils::to_s3s_etag; use super::usecase_storage_compat::object_api_utils::to_s3s_etag;
use crate::app::usecase_storage_compat::quota::checker::QuotaChecker; use super::usecase_storage_compat::quota::checker::QuotaChecker;
use crate::app::usecase_storage_compat::storageclass; use super::usecase_storage_compat::storageclass;
use crate::app::usecase_storage_compat::{ use super::usecase_storage_compat::{
AppReplicationConfigExt as _, AppVersioningConfigExt as _, predict_lifecycle_expiration, validate_restore_request, AppReplicationConfigExt as _, AppVersioningConfigExt as _, predict_lifecycle_expiration, validate_restore_request,
}; };
use crate::app::usecase_storage_compat::{DiskError, is_all_buckets_not_found}; use super::usecase_storage_compat::{DiskError, is_all_buckets_not_found};
use crate::app::usecase_storage_compat::{DynReader, HashReader, WritePlan, wrap_reader}; use super::usecase_storage_compat::{DynReader, HashReader, WritePlan, wrap_reader};
use crate::app::usecase_storage_compat::{ use super::usecase_storage_compat::{
Error as EcstoreError, StorageError, is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found, Error as EcstoreError, StorageError, is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found,
}; };
use crate::app::usecase_storage_compat::{MIN_DISK_COMPRESSIBLE_SIZE, is_disk_compressible}; use super::usecase_storage_compat::{MIN_DISK_COMPRESSIBLE_SIZE, is_disk_compressible};
use crate::app::usecase_storage_compat::{get_lock_acquire_timeout, is_valid_storage_class}; use super::usecase_storage_compat::{get_lock_acquire_timeout, is_valid_storage_class};
use crate::app::usecase_storage_compat::{ use super::usecase_storage_compat::{
lifecycle::{ lifecycle::{
bucket_lifecycle_audit::LcEventSrc, bucket_lifecycle_audit::LcEventSrc,
bucket_lifecycle_ops::{enqueue_transition_immediate, post_restore_opts}, bucket_lifecycle_ops::{enqueue_transition_immediate, post_restore_opts},
@@ -279,12 +279,12 @@ async fn enqueue_transitioned_delete_cleanup(
let _activity_guard = DeleteTailActivityGuard::new(DeleteTailStage::Cleanup); let _activity_guard = DeleteTailActivityGuard::new(DeleteTailStage::Cleanup);
let je = if opts.delete_prefix { let je = if opts.delete_prefix {
crate::app::usecase_storage_compat::lifecycle::tier_sweeper::transitioned_force_delete_journal_entry( super::usecase_storage_compat::lifecycle::tier_sweeper::transitioned_force_delete_journal_entry(
&existing.transitioned_object, &existing.transitioned_object,
) )
} else { } else {
let version_id = opts.version_id.as_ref().and_then(|v| Uuid::parse_str(v).ok()); let version_id = opts.version_id.as_ref().and_then(|v| Uuid::parse_str(v).ok());
crate::app::usecase_storage_compat::lifecycle::tier_sweeper::transitioned_delete_journal_entry( super::usecase_storage_compat::lifecycle::tier_sweeper::transitioned_delete_journal_entry(
version_id, version_id,
opts.versioned, opts.versioned,
opts.version_suspended, opts.version_suspended,
@@ -295,9 +295,9 @@ async fn enqueue_transitioned_delete_cleanup(
return Ok(()); return Ok(());
}; };
crate::app::usecase_storage_compat::lifecycle::tier_delete_journal::persist_tier_delete_journal_entry(store, &je).await?; super::usecase_storage_compat::lifecycle::tier_delete_journal::persist_tier_delete_journal_entry(store, &je).await?;
let mut expiry_state = crate::app::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::GLOBAL_ExpiryState let mut expiry_state = super::usecase_storage_compat::lifecycle::bucket_lifecycle_ops::GLOBAL_ExpiryState
.write() .write()
.await; .await;
if let Err(err) = expiry_state.enqueue_tier_journal_entry(&je).await { if let Err(err) = expiry_state.enqueue_tier_journal_entry(&je).await {
@@ -1603,7 +1603,7 @@ impl DefaultObjectUsecase {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
async fn prepare_get_object_read( async fn prepare_get_object_read(
req: &S3Request<GetObjectInput>, req: &S3Request<GetObjectInput>,
store: &crate::app::usecase_storage_compat::ECStore, store: &super::usecase_storage_compat::ECStore,
manager: &ConcurrencyManager, manager: &ConcurrencyManager,
bucket: &str, bucket: &str,
key: &str, key: &str,
@@ -2197,7 +2197,7 @@ impl DefaultObjectUsecase {
insert_str( insert_str(
&mut metadata, &mut metadata,
SUFFIX_COMPRESSION, SUFFIX_COMPRESSION,
crate::app::usecase_storage_compat::compression_metadata_value(algorithm), super::usecase_storage_compat::compression_metadata_value(algorithm),
); );
insert_str(&mut metadata, SUFFIX_ACTUAL_SIZE, size.to_string()); insert_str(&mut metadata, SUFFIX_ACTUAL_SIZE, size.to_string());
@@ -2212,7 +2212,7 @@ impl DefaultObjectUsecase {
insert_str( insert_str(
&mut opts.user_defined, &mut opts.user_defined,
SUFFIX_COMPRESSION, SUFFIX_COMPRESSION,
crate::app::usecase_storage_compat::compression_metadata_value(algorithm), super::usecase_storage_compat::compression_metadata_value(algorithm),
); );
insert_str(&mut opts.user_defined, SUFFIX_ACTUAL_SIZE, size.to_string()); insert_str(&mut opts.user_defined, SUFFIX_ACTUAL_SIZE, size.to_string());
@@ -2404,7 +2404,7 @@ impl DefaultObjectUsecase {
maybe_enqueue_transition_immediate(&obj_info, LcEventSrc::S3PutObject).await; maybe_enqueue_transition_immediate(&obj_info, LcEventSrc::S3PutObject).await;
// Fast in-memory update for immediate quota and admin usage consistency // Fast in-memory update for immediate quota and admin usage consistency
crate::app::usecase_storage_compat::record_bucket_object_write_memory( super::usecase_storage_compat::record_bucket_object_write_memory(
&bucket, &bucket,
previous_current_size, previous_current_size,
obj_info.size.max(0) as u64, obj_info.size.max(0) as u64,
@@ -3274,7 +3274,7 @@ impl DefaultObjectUsecase {
insert_str( insert_str(
&mut compress_metadata, &mut compress_metadata,
SUFFIX_COMPRESSION, SUFFIX_COMPRESSION,
crate::app::usecase_storage_compat::compression_metadata_value(CompressionAlgorithm::default()), super::usecase_storage_compat::compression_metadata_value(CompressionAlgorithm::default()),
); );
insert_str(&mut compress_metadata, SUFFIX_ACTUAL_SIZE, actual_size.to_string()); insert_str(&mut compress_metadata, SUFFIX_ACTUAL_SIZE, actual_size.to_string());
} else { } else {
@@ -3367,7 +3367,7 @@ impl DefaultObjectUsecase {
// Update quota tracking after successful copy // Update quota tracking after successful copy
if has_bucket_metadata { if has_bucket_metadata {
crate::app::usecase_storage_compat::record_bucket_object_write_memory( super::usecase_storage_compat::record_bucket_object_write_memory(
&bucket, &bucket,
previous_current_size, previous_current_size,
oi.size.max(0) as u64, oi.size.max(0) as u64,
@@ -3649,7 +3649,7 @@ impl DefaultObjectUsecase {
); );
} }
let size = object_sizes[i].max(0) as u64; let size = object_sizes[i].max(0) as u64;
crate::app::usecase_storage_compat::record_bucket_object_delete_memory( super::usecase_storage_compat::record_bucket_object_delete_memory(
&bucket, &bucket,
size, size,
existing_object_infos[i].is_some() && object_to_delete[i].version_id.is_none(), existing_object_infos[i].is_some() && object_to_delete[i].version_id.is_none(),
@@ -3887,7 +3887,7 @@ impl DefaultObjectUsecase {
} }
// Fast in-memory update for immediate quota and admin usage consistency // Fast in-memory update for immediate quota and admin usage consistency
crate::app::usecase_storage_compat::record_bucket_object_delete_memory( super::usecase_storage_compat::record_bucket_object_delete_memory(
&bucket, &bucket,
obj_info.size.max(0) as u64, obj_info.size.max(0) as u64,
opts.version_id.is_none(), opts.version_id.is_none(),
@@ -4864,7 +4864,7 @@ impl DefaultObjectUsecase {
insert_str( insert_str(
&mut metadata, &mut metadata,
SUFFIX_COMPRESSION, SUFFIX_COMPRESSION,
crate::app::usecase_storage_compat::compression_metadata_value(algorithm), super::usecase_storage_compat::compression_metadata_value(algorithm),
); );
insert_str(&mut metadata, SUFFIX_ACTUAL_SIZE, size.to_string()); insert_str(&mut metadata, SUFFIX_ACTUAL_SIZE, size.to_string());
+6 -6
View File
@@ -14,11 +14,11 @@
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::config::WorkloadProfile; use super::super::core_storage_compat::{
use crate::server::cors;
use crate::storage::core_storage_compat::{
BucketMetadata, DEFAULT_READ_BUFFER_SIZE, get_global_bucket_metadata_sys, set_bucket_metadata, BucketMetadata, DEFAULT_READ_BUFFER_SIZE, get_global_bucket_metadata_sys, set_bucket_metadata,
}; };
use crate::config::WorkloadProfile;
use crate::server::cors;
use crate::storage::ecfs::{FS, validate_object_lock_configuration_input}; use crate::storage::ecfs::{FS, validate_object_lock_configuration_input};
use crate::storage::s3_api::common::{rustfs_initiator, rustfs_owner}; use crate::storage::s3_api::common::{rustfs_initiator, rustfs_owner};
use crate::storage::{ use crate::storage::{
@@ -941,8 +941,8 @@ mod tests {
#[tokio::test] #[tokio::test]
async fn test_validate_bucket_object_lock_enabled() { async fn test_validate_bucket_object_lock_enabled() {
use crate::storage::core_storage_compat::bucket_metadata_sys_initialized; use super::super::core_storage_compat::bucket_metadata_sys_initialized;
use crate::storage::core_storage_compat::set_bucket_metadata; use super::super::core_storage_compat::set_bucket_metadata;
use s3s::dto::{ObjectLockConfiguration, ObjectLockEnabled}; use s3s::dto::{ObjectLockConfiguration, ObjectLockEnabled};
use time::OffsetDateTime; use time::OffsetDateTime;
@@ -1781,7 +1781,7 @@ mod tests {
/// with a single-element vec value, matching the format expected by policy evaluation. /// with a single-element vec value, matching the format expected by policy evaluation.
#[test] #[test]
fn test_object_tag_condition_key_format() { fn test_object_tag_condition_key_format() {
use crate::storage::core_storage_compat::decode_tags_to_map; use super::super::core_storage_compat::decode_tags_to_map;
use std::collections::HashMap; use std::collections::HashMap;
let tags_str = "security=public&project=webapp&env=prod"; let tags_str = "security=public&project=webapp&env=prod";
@@ -101,6 +101,7 @@ ALL_STORAGE_COMPAT_SELF_FACADE_PATH_HITS_FILE="${TMP_DIR}/all_storage_compat_sel
RUSTFS_LOCAL_COMPAT_OWNER_SELF_PATH_HITS_FILE="${TMP_DIR}/rustfs_local_compat_owner_self_path_hits.txt" RUSTFS_LOCAL_COMPAT_OWNER_SELF_PATH_HITS_FILE="${TMP_DIR}/rustfs_local_compat_owner_self_path_hits.txt"
RUSTFS_ROOT_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_root_compat_relative_consumer_hits.txt" RUSTFS_ROOT_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_root_compat_relative_consumer_hits.txt"
RUSTFS_STORAGE_CORE_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_storage_core_compat_relative_consumer_hits.txt" RUSTFS_STORAGE_CORE_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_storage_core_compat_relative_consumer_hits.txt"
RUSTFS_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_local_compat_relative_consumer_hits.txt"
SCANNER_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/scanner_bucket_storage_compat_module_hits.txt" SCANNER_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/scanner_bucket_storage_compat_module_hits.txt"
NOTIFY_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/notify_storage_compat_module_hits.txt" NOTIFY_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/notify_storage_compat_module_hits.txt"
OBS_STORAGE_COMPAT_PASSTHROUGH_HITS_FILE="${TMP_DIR}/obs_storage_compat_passthrough_hits.txt" OBS_STORAGE_COMPAT_PASSTHROUGH_HITS_FILE="${TMP_DIR}/obs_storage_compat_passthrough_hits.txt"
@@ -1082,6 +1083,22 @@ if [[ -s "$RUSTFS_STORAGE_CORE_COMPAT_RELATIVE_CONSUMER_HITS_FILE" ]]; then
report_failure "RustFS storage owner consumers must use relative core_storage_compat paths instead of crate-qualified storage owner paths: $(paste -sd '; ' "$RUSTFS_STORAGE_CORE_COMPAT_RELATIVE_CONSUMER_HITS_FILE")" report_failure "RustFS storage owner consumers must use relative core_storage_compat paths instead of crate-qualified storage owner paths: $(paste -sd '; ' "$RUSTFS_STORAGE_CORE_COMPAT_RELATIVE_CONSUMER_HITS_FILE")"
fi fi
(
cd "$ROOT_DIR"
{
rg -n --with-filename 'crate::app::usecase_storage_compat' \
rustfs/src/app/*.rs || true
rg -n --with-filename 'crate::admin::router_storage_compat' \
rustfs/src/admin/router.rs || true
rg -n --with-filename 'crate::storage::core_storage_compat' \
rustfs/src/storage/ecfs_test.rs || true
}
) >"$RUSTFS_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE"
if [[ -s "$RUSTFS_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE" ]]; then
report_failure "RustFS local compatibility consumers must use relative owner paths instead of crate-qualified local compatibility paths: $(paste -sd '; ' "$RUSTFS_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE")"
fi
( (
cd "$ROOT_DIR" cd "$ROOT_DIR"
rg -n --no-heading 'pub\(crate\)\s+use rustfs_ecstore::api::bucket::\{[^}]*\b(?:bucket_target_sys|lifecycle|metadata_sys|replication|versioning|versioning_sys)\b[^}]*\}\s*;' \ rg -n --no-heading 'pub\(crate\)\s+use rustfs_ecstore::api::bucket::\{[^}]*\b(?:bucket_target_sys|lifecycle|metadata_sys|replication|versioning|versioning_sys)\b[^}]*\}\s*;' \