From 5c0164176054335b30b21d5f485e32ecc3c83dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=AD=A3=E8=B6=85?= Date: Sun, 21 Jun 2026 19:36:10 +0800 Subject: [PATCH] refactor: prune storage owner compat re-exports (#3695) --- docs/architecture/crate-boundaries.md | 5 + docs/architecture/migration-progress.md | 49 +++- rustfs/src/storage/ecfs.rs | 14 +- rustfs/src/storage/ecfs_test.rs | 4 +- rustfs/src/storage/rpc/node_service.rs | 12 +- rustfs/src/storage/storage_compat.rs | 276 +++++++++++++++--- scripts/check_architecture_migration_rules.sh | 21 ++ 7 files changed, 306 insertions(+), 75 deletions(-) diff --git a/docs/architecture/crate-boundaries.md b/docs/architecture/crate-boundaries.md index e98730e00..5325b6abd 100644 --- a/docs/architecture/crate-boundaries.md +++ b/docs/architecture/crate-boundaries.md @@ -166,6 +166,11 @@ storage-class config contracts through explicit aliases. The storage compatibility boundary must not restore broad `metadata`, `metadata_sys`, `object_lock`, `policy_sys`, `replication`, `tagging`, `utils`, `versioning`, `versioning_sys`, `object_api_utils`, or `com` passthroughs. +RustFS storage owner `storage_compat.rs` must not re-export ECStore API symbols +directly except temporary trait imports needed for method resolution. Remaining +storage-owner compatibility symbols must be local constants, type aliases, or +wrapper functions so storage-owned global state and helper access stays visible +at the boundary. 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 diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index db7831182..85b806048 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,16 +5,16 @@ 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-root-runtime-compat-wrappers` -- 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`. -- Stacked on: API-085 test and fuzz compatibility alias pruning. +- Branch: `overtrue/arch-storage-owner-compat-wrappers-main` +- 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`. +- Stacked on: `origin/main` after API-086 merged. - PR type for this branch: `pure-move` - Runtime behavior changes: none. -- Rust code changes: prune root RustFS runtime compatibility re-exports into - local aliases, traits, and wrapper functions. -- CI/script changes: guard against restoring root RustFS runtime ECStore API - re-exports. -- Docs changes: record the API-086 root runtime compatibility boundary. +- Rust code changes: prune storage-owner compatibility re-exports into local + constants, type aliases, trait imports, and wrapper functions. +- CI/script changes: guard against restoring storage-owner ECStore API + re-exports except temporary trait imports. +- Docs changes: record the API-087 storage-owner compatibility boundary. ## Phase 0 Tasks @@ -229,6 +229,23 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block - Verification: RustFS compile coverage, root compatibility re-export residual scan, formatting, diff hygiene, architecture guard, pre-commit quality gate, and three-expert review. +- [x] `API-087` Prune storage owner compatibility re-exports. + - Completed slice: replace RustFS storage-owner `storage_compat.rs` ECStore + API re-exports for metadata, object-lock, replication stats, tags, XML + helpers, RPC globals, metrics, global accessors, tier reloads, and local + disk helpers with local aliases and wrappers; keep only temporary trait + imports required for method resolution. + - Acceptance: storage S3 handlers, ECFS replication metrics, RPC node service, + and storage tests keep their existing compatibility names while the storage + owner boundary no longer exposes direct ECStore API symbol re-exports for + functions, constants, globals, or DTO aliases. + - Must preserve: bucket metadata read/write/delete semantics, object-lock + retention checks, replication proxy metrics, object tag encoding/decoding, + XML serialization behavior, RPC signature checks, transition-tier reloads, + global object-store/lock/region access, and local disk lookup behavior. + - Verification: RustFS compile coverage, storage-owner re-export 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 @@ -3262,14 +3279,24 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| -| Quality/architecture | passed | API-086 narrows root RustFS runtime compatibility with local aliases/wrappers and adds an ECStore API re-export guard without adding runtime ownership cycles. | -| Migration preservation | passed | Startup storage, bucket metadata migration/init, replication admission counts, notification init, RPC signature checks, capacity disk references, topology snapshots, table-catalog metadata access, and shutdown behavior remain behind existing local compatibility names. | -| Testing/verification | passed | RustFS compile coverage, root re-export residual scan, migration guard, formatting, diff hygiene, added-line risk scan, full pre-commit, and three-expert review passed. | +| Quality/architecture | passed | API-087 narrows storage-owner compatibility with local aliases/wrappers and an ECStore API re-export guard while leaving only method-resolution trait imports. | +| Migration preservation | passed | Metadata, object-lock, replication proxy metrics, tag/XML helpers, RPC signature checks, tier reload, global accessors, and local disk lookup remain behind existing storage compatibility names. | +| Testing/verification | passed | RustFS compile coverage, storage-owner re-export residual scan, migration guard, formatting, diff hygiene, Rust risk scan, full pre-commit, and three-expert review passed. | ## Verification Notes Passed before push: +- Issue #660 API-087 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. + - Storage-owner ECStore API re-export residual scan: passed. + - Rust added-line risk scan on changed Rust files and guard script: passed. + - `make pre-commit`: passed. + - Issue #660 API-086 current slice: - `cargo check -p rustfs`: passed. - `cargo fmt --all --check`: passed. diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 5838fc07b..2efabac45 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -23,11 +23,11 @@ use crate::storage::options::get_opts; use crate::storage::s3_api::acl; use crate::storage::storage_compat::{ BUCKET_ACCELERATE_CONFIG, BUCKET_LOGGING_CONFIG, BUCKET_REQUEST_PAYMENT_CONFIG, BUCKET_VERSIONING_CONFIG, - BUCKET_WEBSITE_CONFIG, BucketVersioningSys, GLOBAL_REPLICATION_STATS, OBJECT_LOCK_CONFIG, ReplicationConfigurationExt, - StorageError, VersioningApi, check_retention_for_modification, decode_tags, decode_tags_to_map, - delete_bucket_metadata_config, encode_tags, get_bucket_accelerate_config, get_bucket_logging_config, - get_bucket_object_lock_config, get_bucket_replication_config, get_bucket_request_payment_config, get_bucket_website_config, - is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found, serialize, update_bucket_metadata_config, + BUCKET_WEBSITE_CONFIG, BucketVersioningSys, OBJECT_LOCK_CONFIG, ReplicationConfigurationExt, StorageError, VersioningApi, + check_retention_for_modification, decode_tags, decode_tags_to_map, delete_bucket_metadata_config, encode_tags, + get_bucket_accelerate_config, get_bucket_logging_config, get_bucket_object_lock_config, get_bucket_replication_config, + get_bucket_request_payment_config, get_bucket_website_config, is_err_bucket_not_found, is_err_object_not_found, + is_err_version_not_found, record_replication_proxy, serialize, update_bucket_metadata_config, }; use crate::storage::{parse_object_lock_legal_hold, parse_object_lock_retention, validate_bucket_object_lock_enabled}; use crate::table_catalog; @@ -87,9 +87,7 @@ impl FS { if !Self::replication_tagging_enabled(bucket, object).await { return; } - if let Some(stats) = GLOBAL_REPLICATION_STATS.get() { - stats.inc_proxy(bucket, api, is_err).await; - } + record_replication_proxy(bucket, api, is_err).await; } pub async fn get_object_tag_conditions_for_policy( diff --git a/rustfs/src/storage/ecfs_test.rs b/rustfs/src/storage/ecfs_test.rs index 5aa9ff563..79c7f8f7d 100644 --- a/rustfs/src/storage/ecfs_test.rs +++ b/rustfs/src/storage/ecfs_test.rs @@ -941,12 +941,12 @@ mod tests { #[tokio::test] async fn test_validate_bucket_object_lock_enabled() { - use crate::storage::storage_compat::GLOBAL_BUCKET_METADATA_SYS; + use crate::storage::storage_compat::bucket_metadata_sys_initialized; use crate::storage::storage_compat::set_bucket_metadata; use s3s::dto::{ObjectLockConfiguration, ObjectLockEnabled}; use time::OffsetDateTime; - if GLOBAL_BUCKET_METADATA_SYS.get().is_none() { + if !bucket_metadata_sys_initialized() { eprintln!("Skipping test: GLOBAL_BucketMetadataSys not initialized"); return; } diff --git a/rustfs/src/storage/rpc/node_service.rs b/rustfs/src/storage/rpc/node_service.rs index efb44cfc6..ac9e459a8 100644 --- a/rustfs/src/storage/rpc/node_service.rs +++ b/rustfs/src/storage/rpc/node_service.rs @@ -17,11 +17,11 @@ use crate::admin::service::{ site_replication::reload_site_replication_runtime_state, }; use crate::storage::storage_compat::{ - CollectMetricsOpts, DeleteOptions, DiskAPI, DiskError, DiskInfoOptions, DiskStore, FileInfoVersions, GLOBAL_TierConfigMgr, - LocalPeerS3Client, MetricType, PEER_RESTSIGNAL, PEER_RESTSUB_SYS, PeerS3Client, ReadMultipleReq, ReadMultipleResp, - ReadOptions, SERVICE_SIGNAL_REFRESH_CONFIG, SERVICE_SIGNAL_RELOAD_DYNAMIC, UpdateMetadataOpts, all_local_disk_path, - collect_local_metrics, find_local_disk_by_ref, get_global_lock_client, get_local_server_property, load_bucket_metadata, - resolve_object_store_handle, set_bucket_metadata, + CollectMetricsOpts, DeleteOptions, DiskAPI, DiskError, DiskInfoOptions, DiskStore, FileInfoVersions, LocalPeerS3Client, + MetricType, PEER_RESTSIGNAL, PEER_RESTSUB_SYS, PeerS3Client, ReadMultipleReq, ReadMultipleResp, ReadOptions, + SERVICE_SIGNAL_REFRESH_CONFIG, SERVICE_SIGNAL_RELOAD_DYNAMIC, UpdateMetadataOpts, all_local_disk_path, collect_local_metrics, + find_local_disk_by_ref, get_global_lock_client, get_local_server_property, load_bucket_metadata, + reload_transition_tier_config, resolve_object_store_handle, set_bucket_metadata, }; use bytes::Bytes; use futures::Stream; @@ -1046,7 +1046,7 @@ impl Node for NodeService { })); }; - match GLOBAL_TierConfigMgr.write().await.reload(store).await { + match reload_transition_tier_config(store).await { Ok(_) => Ok(Response::new(LoadTransitionTierConfigResponse { success: true, error_info: None, diff --git a/rustfs/src/storage/storage_compat.rs b/rustfs/src/storage/storage_compat.rs index d5840f47f..83be0c390 100644 --- a/rustfs/src/storage/storage_compat.rs +++ b/rustfs/src/storage/storage_compat.rs @@ -12,56 +12,236 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub(crate) use rustfs_ecstore::api::admin::get_local_server_property; -#[cfg(test)] -pub(crate) use rustfs_ecstore::api::bucket::metadata::BucketMetadata; -pub(crate) use rustfs_ecstore::api::bucket::metadata::{ - BUCKET_ACCELERATE_CONFIG, BUCKET_LOGGING_CONFIG, BUCKET_REQUEST_PAYMENT_CONFIG, BUCKET_VERSIONING_CONFIG, - BUCKET_WEBSITE_CONFIG, OBJECT_LOCK_CONFIG, load_bucket_metadata, -}; -#[cfg(test)] -pub(crate) use rustfs_ecstore::api::bucket::metadata_sys::{ - GLOBAL_BucketMetadataSys as GLOBAL_BUCKET_METADATA_SYS, get_global_bucket_metadata_sys, -}; -pub(crate) use rustfs_ecstore::api::bucket::metadata_sys::{ - delete as delete_bucket_metadata_config, get as get_bucket_metadata, get_accelerate_config as get_bucket_accelerate_config, - get_bucket_policy_raw, get_cors_config as get_bucket_cors_config, get_logging_config as get_bucket_logging_config, - get_object_lock_config as get_bucket_object_lock_config, get_public_access_block_config, - get_replication_config as get_bucket_replication_config, get_request_payment_config as get_bucket_request_payment_config, - get_sse_config as get_bucket_sse_config, get_website_config as get_bucket_website_config, set_bucket_metadata, - update as update_bucket_metadata_config, -}; -pub(crate) use rustfs_ecstore::api::bucket::object_lock::objectlock_sys::{ - add_years as add_object_lock_years, check_retention_for_modification, -}; -pub(crate) use rustfs_ecstore::api::bucket::policy_sys::PolicySys; -pub(crate) use rustfs_ecstore::api::bucket::replication::{GLOBAL_REPLICATION_STATS, ReplicationConfigurationExt}; -pub(crate) use rustfs_ecstore::api::bucket::tagging::{decode_tags, decode_tags_to_map, encode_tags}; -pub(crate) use rustfs_ecstore::api::bucket::utils::serialize; +use std::sync::Arc; + +pub(crate) use rustfs_ecstore::api::bucket::replication::ReplicationConfigurationExt; pub(crate) use rustfs_ecstore::api::bucket::versioning::VersioningApi; -pub(crate) use rustfs_ecstore::api::bucket::versioning_sys::BucketVersioningSys; -pub(crate) use rustfs_ecstore::api::client::object_api_utils::to_s3s_etag; +pub(crate) use rustfs_ecstore::api::disk::DiskAPI; +pub(crate) use rustfs_ecstore::api::rpc::PeerS3Client; + +pub(crate) const BUCKET_ACCELERATE_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_ACCELERATE_CONFIG; +pub(crate) const BUCKET_LOGGING_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_LOGGING_CONFIG; +pub(crate) const BUCKET_REQUEST_PAYMENT_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_REQUEST_PAYMENT_CONFIG; +pub(crate) const BUCKET_VERSIONING_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_VERSIONING_CONFIG; +pub(crate) const BUCKET_WEBSITE_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::BUCKET_WEBSITE_CONFIG; +pub(crate) const DEFAULT_READ_BUFFER_SIZE: usize = rustfs_ecstore::api::set_disk::DEFAULT_READ_BUFFER_SIZE; +pub(crate) const OBJECT_LOCK_CONFIG: &str = rustfs_ecstore::api::bucket::metadata::OBJECT_LOCK_CONFIG; +pub(crate) const PEER_RESTSIGNAL: &str = rustfs_ecstore::api::rpc::PEER_RESTSIGNAL; +pub(crate) const PEER_RESTSUB_SYS: &str = rustfs_ecstore::api::rpc::PEER_RESTSUB_SYS; +pub(crate) const SERVICE_SIGNAL_REFRESH_CONFIG: u64 = rustfs_ecstore::api::rpc::SERVICE_SIGNAL_REFRESH_CONFIG; +pub(crate) const SERVICE_SIGNAL_RELOAD_DYNAMIC: u64 = rustfs_ecstore::api::rpc::SERVICE_SIGNAL_RELOAD_DYNAMIC; #[cfg(test)] -pub(crate) use rustfs_ecstore::api::config::com::STORAGE_CLASS_SUB_SYS; -pub(crate) use rustfs_ecstore::api::disk::error::DiskError; -pub(crate) use rustfs_ecstore::api::disk::{ - DeleteOptions, DiskAPI, DiskInfoOptions, DiskStore, FileInfoVersions, ReadMultipleReq, ReadMultipleResp, ReadOptions, - UpdateMetadataOpts, WalkDirOptions, -}; -pub(crate) use rustfs_ecstore::api::error::{ - Error, Result, StorageError, is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found, -}; -pub(crate) use rustfs_ecstore::api::global::{ - GLOBAL_TierConfigMgr, get_global_lock_client, get_global_region, resolve_object_store_handle, -}; -pub(crate) use rustfs_ecstore::api::metrics::{CollectMetricsOpts, MetricType, collect_local_metrics}; -pub(crate) use rustfs_ecstore::api::rio::WriteEncryption; -pub(crate) use rustfs_ecstore::api::rpc::{ - LocalPeerS3Client, PEER_RESTSIGNAL, PEER_RESTSUB_SYS, PeerS3Client, SERVICE_SIGNAL_REFRESH_CONFIG, - SERVICE_SIGNAL_RELOAD_DYNAMIC, verify_rpc_signature, -}; -pub(crate) use rustfs_ecstore::api::set_disk::DEFAULT_READ_BUFFER_SIZE; -pub(crate) use rustfs_ecstore::api::storage::{ECStore, all_local_disk_path, find_local_disk_by_ref}; +pub(crate) const STORAGE_CLASS_SUB_SYS: &str = rustfs_ecstore::api::config::com::STORAGE_CLASS_SUB_SYS; + +pub(crate) type BucketMetadata = rustfs_ecstore::api::bucket::metadata::BucketMetadata; +pub(crate) type BucketVersioningSys = rustfs_ecstore::api::bucket::versioning_sys::BucketVersioningSys; +pub(crate) type CollectMetricsOpts = rustfs_ecstore::api::metrics::CollectMetricsOpts; +pub(crate) type DeleteOptions = rustfs_ecstore::api::disk::DeleteOptions; +pub(crate) type DiskError = rustfs_ecstore::api::disk::error::DiskError; +pub(crate) type DiskInfoOptions = rustfs_ecstore::api::disk::DiskInfoOptions; +pub(crate) type DiskStore = rustfs_ecstore::api::disk::DiskStore; +pub(crate) type ECStore = rustfs_ecstore::api::storage::ECStore; +pub(crate) type Error = rustfs_ecstore::api::error::Error; +pub(crate) type FileInfoVersions = rustfs_ecstore::api::disk::FileInfoVersions; +pub(crate) type LocalPeerS3Client = rustfs_ecstore::api::rpc::LocalPeerS3Client; +pub(crate) type MetricType = rustfs_ecstore::api::metrics::MetricType; +pub(crate) type PolicySys = rustfs_ecstore::api::bucket::policy_sys::PolicySys; +pub(crate) type ReadMultipleReq = rustfs_ecstore::api::disk::ReadMultipleReq; +pub(crate) type ReadMultipleResp = rustfs_ecstore::api::disk::ReadMultipleResp; +pub(crate) type ReadOptions = rustfs_ecstore::api::disk::ReadOptions; +pub(crate) type Result = rustfs_ecstore::api::error::Result; +pub(crate) type StorageError = rustfs_ecstore::api::error::StorageError; +pub(crate) type UpdateMetadataOpts = rustfs_ecstore::api::disk::UpdateMetadataOpts; +pub(crate) type WalkDirOptions = rustfs_ecstore::api::disk::WalkDirOptions; +pub(crate) type WriteEncryption = rustfs_ecstore::api::rio::WriteEncryption; + +pub(crate) async fn get_local_server_property() -> rustfs_madmin::ServerProperties { + rustfs_ecstore::api::admin::get_local_server_property().await +} + +pub(crate) async fn load_bucket_metadata(api: Arc, bucket: &str) -> Result { + rustfs_ecstore::api::bucket::metadata::load_bucket_metadata(api, bucket).await +} + +#[cfg(test)] +pub(crate) fn bucket_metadata_sys_initialized() -> bool { + rustfs_ecstore::api::bucket::metadata_sys::GLOBAL_BucketMetadataSys + .get() + .is_some() +} + +#[cfg(test)] +pub(crate) fn get_global_bucket_metadata_sys() +-> Option>> { + rustfs_ecstore::api::bucket::metadata_sys::get_global_bucket_metadata_sys() +} + +pub(crate) async fn delete_bucket_metadata_config(bucket: &str, config_file: &str) -> Result { + rustfs_ecstore::api::bucket::metadata_sys::delete(bucket, config_file).await +} + +pub(crate) async fn get_bucket_metadata(bucket: &str) -> Result> { + rustfs_ecstore::api::bucket::metadata_sys::get(bucket).await +} + +pub(crate) async fn get_bucket_accelerate_config( + bucket: &str, +) -> Result<(s3s::dto::AccelerateConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_accelerate_config(bucket).await +} + +pub(crate) async fn get_bucket_policy_raw(bucket: &str) -> Result<(String, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_bucket_policy_raw(bucket).await +} + +pub(crate) async fn get_bucket_cors_config(bucket: &str) -> Result<(s3s::dto::CORSConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_cors_config(bucket).await +} + +pub(crate) async fn get_bucket_logging_config(bucket: &str) -> Result<(s3s::dto::BucketLoggingStatus, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_logging_config(bucket).await +} + +pub(crate) async fn get_bucket_object_lock_config( + bucket: &str, +) -> Result<(s3s::dto::ObjectLockConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_object_lock_config(bucket).await +} + +pub(crate) async fn get_public_access_block_config( + bucket: &str, +) -> Result<(s3s::dto::PublicAccessBlockConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_public_access_block_config(bucket).await +} + +pub(crate) async fn get_bucket_replication_config( + bucket: &str, +) -> Result<(s3s::dto::ReplicationConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_replication_config(bucket).await +} + +pub(crate) async fn get_bucket_request_payment_config( + bucket: &str, +) -> Result<(s3s::dto::RequestPaymentConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_request_payment_config(bucket).await +} + +pub(crate) async fn get_bucket_sse_config( + bucket: &str, +) -> Result<(s3s::dto::ServerSideEncryptionConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_sse_config(bucket).await +} + +pub(crate) async fn get_bucket_website_config(bucket: &str) -> Result<(s3s::dto::WebsiteConfiguration, time::OffsetDateTime)> { + rustfs_ecstore::api::bucket::metadata_sys::get_website_config(bucket).await +} + +pub(crate) async fn set_bucket_metadata(bucket: String, bm: BucketMetadata) -> Result<()> { + rustfs_ecstore::api::bucket::metadata_sys::set_bucket_metadata(bucket, bm).await +} + +pub(crate) async fn update_bucket_metadata_config( + bucket: &str, + config_file: &str, + data: Vec, +) -> Result { + rustfs_ecstore::api::bucket::metadata_sys::update(bucket, config_file, data).await +} + +pub(crate) fn add_object_lock_years(dt: time::OffsetDateTime, years: i32) -> time::OffsetDateTime { + rustfs_ecstore::api::bucket::object_lock::objectlock_sys::add_years(dt, years) +} + +pub(crate) fn check_retention_for_modification( + user_defined: &std::collections::HashMap, + new_mode: Option<&str>, + new_retain_until: Option, + bypass_governance: bool, +) -> Option { + rustfs_ecstore::api::bucket::object_lock::objectlock_sys::check_retention_for_modification( + user_defined, + new_mode, + new_retain_until, + bypass_governance, + ) +} + +pub(crate) async fn record_replication_proxy(bucket: &str, api: &str, is_err: bool) { + if let Some(stats) = rustfs_ecstore::api::bucket::replication::GLOBAL_REPLICATION_STATS.get() { + stats.inc_proxy(bucket, api, is_err).await; + } +} + +pub(crate) fn decode_tags(tags: &str) -> Vec { + rustfs_ecstore::api::bucket::tagging::decode_tags(tags) +} + +pub(crate) fn decode_tags_to_map(tags: &str) -> std::collections::HashMap { + rustfs_ecstore::api::bucket::tagging::decode_tags_to_map(tags) +} + +pub(crate) fn encode_tags(tags: Vec) -> String { + rustfs_ecstore::api::bucket::tagging::encode_tags(tags) +} + +pub(crate) fn serialize(val: &T) -> s3s::xml::SerResult> { + rustfs_ecstore::api::bucket::utils::serialize(val) +} + +pub(crate) fn to_s3s_etag(etag: &str) -> s3s::dto::ETag { + rustfs_ecstore::api::client::object_api_utils::to_s3s_etag(etag) +} + +pub(crate) fn is_err_bucket_not_found(err: &Error) -> bool { + rustfs_ecstore::api::error::is_err_bucket_not_found(err) +} + +pub(crate) fn is_err_object_not_found(err: &Error) -> bool { + rustfs_ecstore::api::error::is_err_object_not_found(err) +} + +pub(crate) fn is_err_version_not_found(err: &Error) -> bool { + rustfs_ecstore::api::error::is_err_version_not_found(err) +} + +pub(crate) fn get_global_lock_client() -> Option> { + rustfs_ecstore::api::global::get_global_lock_client() +} + +pub(crate) fn get_global_region() -> Option { + rustfs_ecstore::api::global::get_global_region() +} + +pub(crate) fn resolve_object_store_handle() -> Option> { + rustfs_ecstore::api::global::resolve_object_store_handle() +} + +pub(crate) async fn collect_local_metrics( + types: MetricType, + opts: &CollectMetricsOpts, +) -> rustfs_madmin::metrics::RealtimeMetrics { + rustfs_ecstore::api::metrics::collect_local_metrics(types, opts).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) +} + +pub(crate) async fn reload_transition_tier_config(api: Arc) -> std::io::Result<()> { + rustfs_ecstore::api::global::GLOBAL_TierConfigMgr + .write() + .await + .reload(api) + .await +} + +pub(crate) async fn all_local_disk_path() -> Vec { + rustfs_ecstore::api::storage::all_local_disk_path().await +} + +pub(crate) async fn find_local_disk_by_ref(disk_ref: &str) -> Option { + rustfs_ecstore::api::storage::find_local_disk_by_ref(disk_ref).await +} pub(crate) type GetObjectReader = ::GetObjectReader; pub(crate) type ObjectInfo = ::ObjectInfo; diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 02dc48748..57ce16b50 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -83,6 +83,7 @@ RUSTFS_ROOT_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_root_bucke RUSTFS_ROOT_RUNTIME_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_root_runtime_storage_compat_module_hits.txt" RUSTFS_ADMIN_CONFIG_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_admin_config_storage_compat_module_hits.txt" RUSTFS_STORAGE_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_storage_bucket_storage_compat_module_hits.txt" +RUSTFS_STORAGE_OWNER_COMPAT_REEXPORT_HITS_FILE="${TMP_DIR}/rustfs_storage_owner_compat_reexport_hits.txt" RUSTFS_ADMIN_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_admin_bucket_storage_compat_module_hits.txt" RUSTFS_APP_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/rustfs_app_bucket_storage_compat_module_hits.txt" SCANNER_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/scanner_bucket_storage_compat_module_hits.txt" @@ -827,6 +828,26 @@ if [[ -s "$RUSTFS_STORAGE_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE" ]]; then report_failure "RustFS storage compatibility must expose bucket/object-api/config contracts as explicit aliases: $(paste -sd '; ' "$RUSTFS_STORAGE_BUCKET_STORAGE_COMPAT_MODULE_HITS_FILE")" fi +( + cd "$ROOT_DIR" + perl -0ne ' + while (/pub\(crate\)\s+use\s+rustfs_ecstore::api::([^;]+);/g) { + my $path = $1; + $path =~ s/\s+/ /g; + $path =~ s/^\s+|\s+$//g; + next if $path eq "bucket::replication::ReplicationConfigurationExt"; + next if $path eq "bucket::versioning::VersioningApi"; + next if $path eq "disk::DiskAPI"; + next if $path eq "rpc::PeerS3Client"; + print "$ARGV:pub(crate) use rustfs_ecstore::api::$path;\n"; + } + ' rustfs/src/storage/storage_compat.rs || true +) >"$RUSTFS_STORAGE_OWNER_COMPAT_REEXPORT_HITS_FILE" + +if [[ -s "$RUSTFS_STORAGE_OWNER_COMPAT_REEXPORT_HITS_FILE" ]]; then + report_failure "RustFS storage owner compatibility must use local aliases or wrappers instead of re-exporting ECStore API symbols except temporary traits: $(paste -sd '; ' "$RUSTFS_STORAGE_OWNER_COMPAT_REEXPORT_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --no-heading 'pub\(crate\)\s+use rustfs_ecstore::api::bucket::\{[^}]*\b(?:bandwidth|bucket_target_sys|lifecycle|metadata|metadata_sys|quota|replication|target|utils|versioning|versioning_sys)\b[^}]*\}\s*;|pub\(crate\)\s+use rustfs_ecstore::api::bucket::(?:bandwidth|bucket_target_sys|lifecycle|metadata|metadata_sys|quota|replication|target|utils|versioning|versioning_sys)\s*;|pub\(crate\)\s+use rustfs_ecstore::api::config::\{[^}]*\bstorageclass\b[^}]*\}\s*;|pub\(crate\)\s+use rustfs_ecstore::api::config::storageclass\s*;' \