refactor: prune root e2e raw facade paths (#3705)

This commit is contained in:
安正超
2026-06-22 03:30:03 +08:00
committed by GitHub
parent d39815470e
commit b8a0fc4e04
5 changed files with 135 additions and 96 deletions
+9 -7
View File
@@ -14,13 +14,15 @@
#![allow(dead_code, unused_imports)]
pub(crate) type BucketTargetSys = rustfs_ecstore::api::bucket::bucket_target_sys::BucketTargetSys;
pub(crate) type TonicInterceptor = rustfs_ecstore::api::rpc::TonicInterceptor;
pub(crate) type VolumeInfo = rustfs_ecstore::api::disk::VolumeInfo;
pub(crate) type WalkDirOptions = rustfs_ecstore::api::disk::WalkDirOptions;
use rustfs_ecstore::api::{bucket as ecstore_bucket, disk as ecstore_disk, rpc as ecstore_rpc};
pub(crate) type BucketTargetSys = ecstore_bucket::bucket_target_sys::BucketTargetSys;
pub(crate) type TonicInterceptor = ecstore_rpc::TonicInterceptor;
pub(crate) type VolumeInfo = ecstore_disk::VolumeInfo;
pub(crate) type WalkDirOptions = ecstore_disk::WalkDirOptions;
pub(crate) fn gen_tonic_signature_interceptor() -> TonicInterceptor {
TonicInterceptor::Signature(rustfs_ecstore::api::rpc::gen_tonic_signature_interceptor())
TonicInterceptor::Signature(ecstore_rpc::gen_tonic_signature_interceptor())
}
pub(crate) async fn node_service_time_out_client(
@@ -32,7 +34,7 @@ pub(crate) async fn node_service_time_out_client(
>,
Box<dyn std::error::Error>,
> {
rustfs_ecstore::api::rpc::node_service_time_out_client(addr, interceptor).await
ecstore_rpc::node_service_time_out_client(addr, interceptor).await
}
pub(crate) async fn node_service_time_out_client_no_auth(
@@ -43,5 +45,5 @@ pub(crate) async fn node_service_time_out_client_no_auth(
>,
Box<dyn std::error::Error>,
> {
rustfs_ecstore::api::rpc::node_service_time_out_client_no_auth(addr).await
ecstore_rpc::node_service_time_out_client_no_auth(addr).await
}
+3
View File
@@ -194,6 +194,9 @@ Peripheral consumer storage compatibility boundaries must follow the same
pattern. IAM, heal, scanner, notify, observability, Swift, S3 Select, test, and
fuzz storage compatibility modules keep raw ECStore facade access centralized
behind local `ecstore_*` module aliases.
RustFS root runtime and e2e storage compatibility boundaries must follow the
same pattern, keeping raw ECStore facade access centralized behind local
`ecstore_*` module aliases.
Scanner, notify, observability, and e2e `storage_compat.rs` boundaries must
also stay narrow. Scanner must not restore grouped bucket compatibility exports
for target, lifecycle, metadata, replication, or versioning modules. Notify
+38 -11
View File
@@ -5,16 +5,17 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
## Current Context
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
- Branch: `overtrue/arch-outer-consumer-compat-raw-facade-prune`
- 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`.
- Stacked on: `overtrue/arch-outer-compat-raw-facade-prune` pending API-093 merge.
- Branch: `overtrue/arch-root-e2e-compat-raw-facade-prune`
- 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`.
- Stacked on: `overtrue/arch-outer-consumer-compat-raw-facade-prune` pending API-094 merge.
- PR type for this branch: `pure-move`
- Runtime behavior changes: none.
- Rust code changes: centralize peripheral consumer storage compatibility raw
ECStore facade paths behind local `ecstore_*` module aliases.
- CI/script changes: guard peripheral consumer storage compatibility boundaries
against restoring scattered raw ECStore facade paths.
- Docs changes: record the API-094 consumer facade path cleanup.
- Rust code changes: centralize RustFS root runtime and e2e storage
compatibility raw ECStore facade paths behind local `ecstore_*` module
aliases.
- CI/script changes: guard RustFS root runtime and e2e storage compatibility
boundaries against restoring scattered raw ECStore facade paths.
- Docs changes: record the API-095 root/e2e facade path cleanup.
## Phase 0 Tasks
@@ -348,6 +349,19 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
- Verification: RustFS compile coverage, consumer raw facade path residual
scan, migration guard, formatting, diff hygiene, Rust risk scan,
pre-commit quality gate, and three-expert review.
- [x] `API-095` Prune root/e2e raw facade paths.
- Completed slice: replace scattered raw `rustfs_ecstore::api::...` paths in
the RustFS root runtime and e2e storage compatibility boundaries with local
`ecstore_*` module aliases.
- Acceptance: `rustfs/src/storage_compat.rs` and
`crates/e2e_test/src/storage_compat.rs` no longer contain raw
`rustfs_ecstore::api::...` facade paths outside centralized local alias
imports.
- Must preserve: root runtime metadata/config/global/storage/RPC wrappers and
e2e RPC harness aliases.
- Verification: RustFS compile coverage, root/e2e raw facade path residual
scan, migration guard, formatting, diff hygiene, Rust risk scan,
pre-commit quality gate, and three-expert review.
- [x] `G-012` Inventory placement and repair invariants.
- Acceptance:
[`placement-repair-invariants.md`](placement-repair-invariants.md) records
@@ -3381,14 +3395,27 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
| Expert | Status | Notes |
|---|---|---|
| Quality/architecture | passed | API-094 centralizes peripheral consumer ECStore facade paths behind local `ecstore_*` module aliases without adding nested compatibility modules. |
| Migration preservation | passed | IAM config and notifications, heal disk lookup, scanner lifecycle and tier helpers, notify server config IO, observability runtime metrics, Swift metadata wrappers, S3 Select error checks, and test/fuzz harness wrappers keep the same ECStore contracts. |
| Testing/verification | passed | RustFS compile coverage, consumer raw facade path residual scan, migration and layer guards, formatting, diff hygiene, Rust risk scan, full pre-commit, and three-expert review passed. |
| Quality/architecture | passed | API-095 centralizes RustFS root runtime and e2e ECStore facade paths behind local `ecstore_*` module aliases without adding nested compatibility modules. |
| Migration preservation | passed | Root runtime metadata/config/global/storage/RPC wrappers and e2e RPC harness aliases keep the same ECStore contracts. |
| Testing/verification | passed | RustFS compile coverage, root/e2e raw facade path residual scan, migration and layer guards, formatting, diff hygiene, Rust risk scan, full pre-commit, and three-expert review passed. |
## Verification Notes
Passed before push:
- Issue #660 API-095 current slice:
- `cargo check -p rustfs`: 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 root/e2e raw facade path residual scan: passed.
- Rust risk scan on changed Rust files: passed.
- `make pre-commit`: passed; nextest run
`a1771057-5015-4861-9a38-b856c8abb6f6`, 6354 passed, 111 skipped; doctests
passed.
- Issue #660 API-094 current slice:
- `cargo check -p rustfs`: passed.
- `cargo fmt --all --check`: passed.
+74 -78
View File
@@ -14,29 +14,35 @@
use std::{collections::HashMap, sync::Arc, time::Duration};
pub(crate) const BUCKET_TABLE_CATALOG_META_PREFIX: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_TABLE_CATALOG_META_PREFIX;
use rustfs_ecstore::api::{
bucket as ecstore_bucket, cluster as ecstore_cluster, config as ecstore_config, disk as ecstore_disk, error as ecstore_error,
event as ecstore_event, global as ecstore_global, layout as ecstore_layout, notification as ecstore_notification,
rpc as ecstore_rpc, set_disk as ecstore_set_disk, storage as ecstore_storage,
};
pub(crate) const BUCKET_TABLE_CATALOG_META_PREFIX: &str = ecstore_bucket::metadata::BUCKET_TABLE_CATALOG_META_PREFIX;
pub(crate) const BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX: &str =
rustfs_ecstore::api::bucket::metadata::BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX;
pub(crate) const BUCKET_TABLE_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_TABLE_CONFIG;
pub(crate) const BUCKET_TABLE_RESERVED_PREFIX: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_TABLE_RESERVED_PREFIX;
pub(crate) const RUSTFS_META_BUCKET: &str = rustfs_ecstore::api::disk::RUSTFS_META_BUCKET;
pub(crate) const TONIC_RPC_PREFIX: &str = rustfs_ecstore::api::rpc::TONIC_RPC_PREFIX;
ecstore_bucket::metadata::BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX;
pub(crate) const BUCKET_TABLE_CONFIG: &str = ecstore_bucket::metadata::BUCKET_TABLE_CONFIG;
pub(crate) const BUCKET_TABLE_RESERVED_PREFIX: &str = ecstore_bucket::metadata::BUCKET_TABLE_RESERVED_PREFIX;
pub(crate) const RUSTFS_META_BUCKET: &str = ecstore_disk::RUSTFS_META_BUCKET;
pub(crate) const TONIC_RPC_PREFIX: &str = ecstore_rpc::TONIC_RPC_PREFIX;
pub(crate) type ECStore = rustfs_ecstore::api::storage::ECStore;
pub(crate) type EcstoreError = rustfs_ecstore::api::error::Error;
pub(crate) type EcstoreEventArgs = rustfs_ecstore::api::event::EventArgs;
pub(crate) type EcstoreResult<T> = rustfs_ecstore::api::error::Result<T>;
pub(crate) type Endpoint = rustfs_ecstore::api::disk::endpoint::Endpoint;
pub(crate) type EndpointServerPools = rustfs_ecstore::api::layout::EndpointServerPools;
pub(crate) type QuotaError = rustfs_ecstore::api::bucket::quota::QuotaError;
pub(crate) type StorageError = rustfs_ecstore::api::error::StorageError;
pub(crate) type ECStore = ecstore_storage::ECStore;
pub(crate) type EcstoreError = ecstore_error::Error;
pub(crate) type EcstoreEventArgs = ecstore_event::EventArgs;
pub(crate) type EcstoreResult<T> = ecstore_error::Result<T>;
pub(crate) type Endpoint = ecstore_disk::endpoint::Endpoint;
pub(crate) type EndpointServerPools = ecstore_layout::EndpointServerPools;
pub(crate) type QuotaError = ecstore_bucket::quota::QuotaError;
pub(crate) type StorageError = ecstore_error::StorageError;
#[cfg(test)]
pub(crate) type DisksLayout = rustfs_ecstore::api::layout::DisksLayout;
pub(crate) type DisksLayout = ecstore_layout::DisksLayout;
#[cfg(test)]
pub(crate) type Endpoints = rustfs_ecstore::api::layout::Endpoints;
pub(crate) type Endpoints = ecstore_layout::Endpoints;
#[cfg(test)]
pub(crate) type PoolEndpoints = rustfs_ecstore::api::layout::PoolEndpoints;
pub(crate) type PoolEndpoints = ecstore_layout::PoolEndpoints;
pub(crate) trait DiskAPI {
fn endpoint(&self) -> Endpoint;
@@ -45,68 +51,62 @@ pub(crate) trait DiskAPI {
impl<T> DiskAPI for T
where
T: rustfs_ecstore::api::disk::DiskAPI,
T: ecstore_disk::DiskAPI,
{
fn endpoint(&self) -> Endpoint {
rustfs_ecstore::api::disk::DiskAPI::endpoint(self)
ecstore_disk::DiskAPI::endpoint(self)
}
fn to_string(&self) -> String {
rustfs_ecstore::api::disk::DiskAPI::to_string(self)
ecstore_disk::DiskAPI::to_string(self)
}
}
pub(crate) fn table_catalog_path_hash(value: &str) -> String {
rustfs_ecstore::api::bucket::metadata::table_catalog_path_hash(value)
ecstore_bucket::metadata::table_catalog_path_hash(value)
}
pub(crate) async fn get_bucket_metadata(
bucket: &str,
) -> rustfs_ecstore::api::error::Result<Arc<rustfs_ecstore::api::bucket::metadata::BucketMetadata>> {
rustfs_ecstore::api::bucket::metadata_sys::get(bucket).await
pub(crate) async fn get_bucket_metadata(bucket: &str) -> ecstore_error::Result<Arc<ecstore_bucket::metadata::BucketMetadata>> {
ecstore_bucket::metadata_sys::get(bucket).await
}
pub(crate) fn get_global_bucket_metadata_sys()
-> Option<Arc<tokio::sync::RwLock<rustfs_ecstore::api::bucket::metadata_sys::BucketMetadataSys>>> {
rustfs_ecstore::api::bucket::metadata_sys::get_global_bucket_metadata_sys()
pub(crate) fn get_global_bucket_metadata_sys() -> Option<Arc<tokio::sync::RwLock<ecstore_bucket::metadata_sys::BucketMetadataSys>>>
{
ecstore_bucket::metadata_sys::get_global_bucket_metadata_sys()
}
pub(crate) async fn get_notification_config(
bucket: &str,
) -> rustfs_ecstore::api::error::Result<Option<s3s::dto::NotificationConfiguration>> {
rustfs_ecstore::api::bucket::metadata_sys::get_notification_config(bucket).await
pub(crate) async fn get_notification_config(bucket: &str) -> ecstore_error::Result<Option<s3s::dto::NotificationConfiguration>> {
ecstore_bucket::metadata_sys::get_notification_config(bucket).await
}
pub(crate) async fn init_bucket_metadata_sys(api: Arc<ECStore>, buckets: Vec<String>) {
rustfs_ecstore::api::bucket::metadata_sys::init_bucket_metadata_sys(api, buckets).await;
ecstore_bucket::metadata_sys::init_bucket_metadata_sys(api, buckets).await;
}
pub(crate) async fn try_migrate_bucket_metadata(store: Arc<ECStore>) {
rustfs_ecstore::api::bucket::migration::try_migrate_bucket_metadata(store).await;
ecstore_bucket::migration::try_migrate_bucket_metadata(store).await;
}
pub(crate) async fn try_migrate_iam_config(store: Arc<ECStore>) {
rustfs_ecstore::api::bucket::migration::try_migrate_iam_config(store).await;
ecstore_bucket::migration::try_migrate_iam_config(store).await;
}
pub(crate) fn get_global_replication_pool() -> Option<Arc<rustfs_ecstore::api::bucket::replication::DynReplicationPool>> {
rustfs_ecstore::api::bucket::replication::get_global_replication_pool()
pub(crate) fn get_global_replication_pool() -> Option<Arc<ecstore_bucket::replication::DynReplicationPool>> {
ecstore_bucket::replication::get_global_replication_pool()
}
pub(crate) fn replication_queue_current_count() -> Option<i64> {
rustfs_ecstore::api::bucket::replication::GLOBAL_REPLICATION_STATS
.get()
.and_then(|stats| {
stats
.q_cache
.try_lock()
.ok()
.map(|cache| cache.sr_queue_stats.curr.get_current_count())
})
ecstore_bucket::replication::GLOBAL_REPLICATION_STATS.get().and_then(|stats| {
stats
.q_cache
.try_lock()
.ok()
.map(|cache| cache.sr_queue_stats.curr.get_current_count())
})
}
pub(crate) async fn init_background_replication(storage: Arc<ECStore>) {
rustfs_ecstore::api::bucket::replication::init_background_replication(storage).await;
ecstore_bucket::replication::init_background_replication(storage).await;
}
pub(crate) fn topology_snapshot_from_endpoint_pools_with_capabilities(
@@ -114,104 +114,100 @@ pub(crate) fn topology_snapshot_from_endpoint_pools_with_capabilities(
capabilities: rustfs_storage_api::TopologyCapabilities,
disk_capabilities: rustfs_storage_api::DiskCapabilities,
) -> rustfs_storage_api::TopologySnapshot {
rustfs_ecstore::api::cluster::topology_snapshot_from_endpoint_pools_with_capabilities(
endpoint_pools,
capabilities,
disk_capabilities,
)
ecstore_cluster::topology_snapshot_from_endpoint_pools_with_capabilities(endpoint_pools, capabilities, disk_capabilities)
}
pub(crate) async fn read_ecstore_config(api: Arc<ECStore>, file: &str) -> EcstoreResult<Vec<u8>> {
rustfs_ecstore::api::config::com::read_config(api, file).await
ecstore_config::com::read_config(api, file).await
}
pub(crate) async fn save_ecstore_config(api: Arc<ECStore>, file: &str, data: Vec<u8>) -> EcstoreResult<()> {
rustfs_ecstore::api::config::com::save_config(api, file, data).await
ecstore_config::com::save_config(api, file, data).await
}
pub(crate) fn init_ecstore_config() {
rustfs_ecstore::api::config::init();
ecstore_config::init();
}
pub(crate) async fn init_global_config_sys(api: Arc<ECStore>) -> EcstoreResult<()> {
rustfs_ecstore::api::config::init_global_config_sys(api).await
ecstore_config::init_global_config_sys(api).await
}
pub(crate) async fn try_migrate_server_config(api: Arc<ECStore>) {
rustfs_ecstore::api::config::try_migrate_server_config(api).await;
ecstore_config::try_migrate_server_config(api).await;
}
pub(crate) fn register_event_dispatch_hook<F>(hook: F) -> bool
where
F: Fn(EcstoreEventArgs) + Send + Sync + 'static,
{
rustfs_ecstore::api::event::register_event_dispatch_hook(hook)
ecstore_event::register_event_dispatch_hook(hook)
}
pub(crate) fn get_global_endpoints_opt() -> Option<EndpointServerPools> {
rustfs_ecstore::api::global::get_global_endpoints_opt()
ecstore_global::get_global_endpoints_opt()
}
pub(crate) fn get_global_lock_clients() -> Option<&'static HashMap<String, Arc<dyn rustfs_lock::client::LockClient>>> {
rustfs_ecstore::api::global::get_global_lock_clients()
ecstore_global::get_global_lock_clients()
}
pub(crate) fn get_global_region() -> Option<s3s::region::Region> {
rustfs_ecstore::api::global::get_global_region()
ecstore_global::get_global_region()
}
pub(crate) async fn is_dist_erasure() -> bool {
rustfs_ecstore::api::global::is_dist_erasure().await
ecstore_global::is_dist_erasure().await
}
pub(crate) fn resolve_object_store_handle() -> Option<Arc<ECStore>> {
rustfs_ecstore::api::global::resolve_object_store_handle()
ecstore_global::resolve_object_store_handle()
}
pub(crate) fn set_global_endpoints(eps: Vec<rustfs_ecstore::api::layout::PoolEndpoints>) {
rustfs_ecstore::api::global::set_global_endpoints(eps);
pub(crate) fn set_global_endpoints(eps: Vec<ecstore_layout::PoolEndpoints>) {
ecstore_global::set_global_endpoints(eps);
}
pub(crate) fn set_global_region(region: s3s::region::Region) {
rustfs_ecstore::api::global::set_global_region(region);
ecstore_global::set_global_region(region);
}
pub(crate) fn set_global_rustfs_port(value: u16) {
rustfs_ecstore::api::global::set_global_rustfs_port(value);
ecstore_global::set_global_rustfs_port(value);
}
pub(crate) fn shutdown_background_services() {
rustfs_ecstore::api::global::shutdown_background_services();
ecstore_global::shutdown_background_services();
}
pub(crate) async fn update_erasure_type(setup_type: rustfs_ecstore::api::layout::SetupType) {
rustfs_ecstore::api::global::update_erasure_type(setup_type).await;
pub(crate) async fn update_erasure_type(setup_type: ecstore_layout::SetupType) {
ecstore_global::update_erasure_type(setup_type).await;
}
pub(crate) async fn new_global_notification_sys(eps: EndpointServerPools) -> EcstoreResult<()> {
rustfs_ecstore::api::notification::new_global_notification_sys(eps).await
ecstore_notification::new_global_notification_sys(eps).await
}
pub(crate) fn verify_rpc_signature(url: &str, method: &http::Method, headers: &http::HeaderMap) -> std::io::Result<()> {
rustfs_ecstore::api::rpc::verify_rpc_signature(url, method, headers)
ecstore_rpc::verify_rpc_signature(url, method, headers)
}
pub(crate) fn get_lock_acquire_timeout() -> Duration {
rustfs_ecstore::api::set_disk::get_lock_acquire_timeout()
ecstore_set_disk::get_lock_acquire_timeout()
}
pub(crate) async fn all_local_disk() -> Vec<rustfs_ecstore::api::disk::DiskStore> {
rustfs_ecstore::api::storage::all_local_disk().await
pub(crate) async fn all_local_disk() -> Vec<ecstore_disk::DiskStore> {
ecstore_storage::all_local_disk().await
}
pub(crate) async fn init_local_disks(endpoint_pools: EndpointServerPools) -> EcstoreResult<()> {
rustfs_ecstore::api::storage::init_local_disks(endpoint_pools).await
ecstore_storage::init_local_disks(endpoint_pools).await
}
pub(crate) fn init_lock_clients(endpoint_pools: EndpointServerPools) {
rustfs_ecstore::api::storage::init_lock_clients(endpoint_pools);
ecstore_storage::init_lock_clients(endpoint_pools);
}
pub(crate) async fn prewarm_local_disk_id_map() {
rustfs_ecstore::api::storage::prewarm_local_disk_id_map().await;
ecstore_storage::prewarm_local_disk_id_map().await;
}
@@ -91,6 +91,7 @@ RUSTFS_OUTER_COMPAT_SIGNATURE_ALIAS_HITS_FILE="${TMP_DIR}/rustfs_outer_compat_si
RUSTFS_STORAGE_COMPAT_RAW_FACADE_PATH_HITS_FILE="${TMP_DIR}/rustfs_storage_compat_raw_facade_path_hits.txt"
RUSTFS_APP_ADMIN_COMPAT_RAW_FACADE_PATH_HITS_FILE="${TMP_DIR}/rustfs_app_admin_compat_raw_facade_path_hits.txt"
OUTER_CONSUMER_COMPAT_RAW_FACADE_PATH_HITS_FILE="${TMP_DIR}/outer_consumer_compat_raw_facade_path_hits.txt"
RUSTFS_ROOT_E2E_COMPAT_RAW_FACADE_PATH_HITS_FILE="${TMP_DIR}/rustfs_root_e2e_compat_raw_facade_path_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"
OBS_STORAGE_COMPAT_PASSTHROUGH_HITS_FILE="${TMP_DIR}/obs_storage_compat_passthrough_hits.txt"
@@ -949,6 +950,16 @@ if [[ -s "$OUTER_CONSUMER_COMPAT_RAW_FACADE_PATH_HITS_FILE" ]]; then
report_failure "outer consumer storage compatibility must use local ecstore_* module aliases instead of scattered raw ECStore facade paths: $(paste -sd '; ' "$OUTER_CONSUMER_COMPAT_RAW_FACADE_PATH_HITS_FILE")"
fi
(
cd "$ROOT_DIR"
rg -n --no-heading 'rustfs_ecstore::api::' rustfs/src/storage_compat.rs crates/e2e_test/src/storage_compat.rs \
| rg -v '^[^:]+:[0-9]+:use rustfs_ecstore::api::\{' || true
) >"$RUSTFS_ROOT_E2E_COMPAT_RAW_FACADE_PATH_HITS_FILE"
if [[ -s "$RUSTFS_ROOT_E2E_COMPAT_RAW_FACADE_PATH_HITS_FILE" ]]; then
report_failure "RustFS root/e2e storage compatibility must use local ecstore_* module aliases instead of scattered raw ECStore facade paths: $(paste -sd '; ' "$RUSTFS_ROOT_E2E_COMPAT_RAW_FACADE_PATH_HITS_FILE")"
fi
(
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*;' \