diff --git a/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs b/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs index 8947baf53..c9f360a62 100644 --- a/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs +++ b/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs @@ -2868,12 +2868,12 @@ mod tests { use crate::error::is_err_invalid_upload_id; use crate::set_disk::{RUSTFS_MULTIPART_BUCKET_KEY, RUSTFS_MULTIPART_OBJECT_KEY}; use crate::store::ECStore; - use crate::store_api::{BucketOperations, MultipartOperations, ObjectInfo, ObjectOptions, PutObjReader}; + use crate::store_api::{MultipartOperations, ObjectInfo, ObjectOptions, PutObjReader}; use futures::FutureExt; use rustfs_common::metrics::{IlmAction, global_metrics}; use rustfs_config::ENV_TRANSITION_WORKERS_ABSOLUTE_MAX; use rustfs_filemeta::{ReplicateDecision, VersionPurgeStatusType}; - use rustfs_storage_api::{BucketOptions, MakeBucketOptions}; + use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions}; use s3s::dto::{BucketLifecycleConfiguration, ExpirationStatus, LifecycleExpiration, LifecycleRule, Timestamp}; use serial_test::serial; use sha2::{Digest, Sha256}; diff --git a/crates/ecstore/src/bucket/lifecycle/tier_free_version_recovery.rs b/crates/ecstore/src/bucket/lifecycle/tier_free_version_recovery.rs index 28b3a3c9a..6b673eba0 100644 --- a/crates/ecstore/src/bucket/lifecycle/tier_free_version_recovery.rs +++ b/crates/ecstore/src/bucket/lifecycle/tier_free_version_recovery.rs @@ -20,8 +20,8 @@ use tokio_util::sync::CancellationToken; use crate::disk::RUSTFS_META_BUCKET; use crate::error::Result; use crate::store::ECStore; -use crate::store_api::{BucketOperations, ListOperations, ObjectInfo, ObjectInfoOrErr, WalkOptions}; -use rustfs_storage_api::BucketOptions; +use crate::store_api::{ListOperations, ObjectInfo, ObjectInfoOrErr, WalkOptions}; +use rustfs_storage_api::{BucketOperations, BucketOptions}; pub const DEFAULT_FREE_VERSION_RECOVERY_LIMIT: usize = 1_000; const DEFAULT_FREE_VERSION_RECOVERY_SCAN_LIMIT: usize = 10_000; diff --git a/crates/ecstore/src/bucket/migration.rs b/crates/ecstore/src/bucket/migration.rs index 91e0596fe..c881b34df 100644 --- a/crates/ecstore/src/bucket/migration.rs +++ b/crates/ecstore/src/bucket/migration.rs @@ -17,11 +17,11 @@ use crate::bucket::metadata::BUCKET_METADATA_FILE; use crate::bucket::replication::{decode_resync_file, encode_resync_file}; use crate::disk::{BUCKET_META_PREFIX, MIGRATING_META_BUCKET, RUSTFS_META_BUCKET}; -use crate::store_api::{BucketOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}; +use crate::store_api::{ListOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}; use http::HeaderMap; use rustfs_policy::auth::UserIdentity; use rustfs_policy::policy::PolicyDoc; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_utils::path::SLASH_SEPARATOR; use serde::{Deserialize, Serialize}; use std::sync::Arc; @@ -179,7 +179,7 @@ fn normalize_bucket_meta_blob(path: &str, data: &[u8]) -> std::result::Result(store: Arc) where - S: BucketOperations + ObjectIO + ObjectOperations, + S: BucketOperations + ObjectIO + ObjectOperations, { let buckets_list = match store .list_bucket(&BucketOptions { diff --git a/crates/ecstore/src/pools.rs b/crates/ecstore/src/pools.rs index 2f52fd116..c0b31bc31 100644 --- a/crates/ecstore/src/pools.rs +++ b/crates/ecstore/src/pools.rs @@ -38,7 +38,7 @@ use crate::error::{ use crate::notification_sys::get_global_notification_sys; use crate::resolve_object_store_handle; use crate::set_disk::SetDisks; -use crate::store_api::{BucketOperations, GetObjectReader, HealOperations, ObjectIO, ObjectOperations, ObjectOptions}; +use crate::store_api::{GetObjectReader, HealOperations, ObjectIO, ObjectOperations, ObjectOptions}; use crate::{global::GLOBAL_LifecycleSys, sets::Sets, store::ECStore}; use byteorder::{ByteOrder, LittleEndian, WriteBytesExt}; use futures::{StreamExt, future::BoxFuture, stream::FuturesUnordered}; @@ -50,7 +50,7 @@ use rustfs_common::defer; use rustfs_common::heal_channel::HealOpts; use rustfs_concurrency::workers::Workers; use rustfs_filemeta::{FileInfoVersions, MetaCacheEntries, MetaCacheEntry, MetadataResolutionParams}; -use rustfs_storage_api::{BucketOptions, MakeBucketOptions, StorageAdminApi}; +use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions, StorageAdminApi}; use rustfs_utils::path::{encode_dir_object, path_join, path_to_bucket_object, path_to_bucket_object_with_base_path}; use s3s::dto::{BucketLifecycleConfiguration, DefaultRetention, ReplicationConfiguration}; use serde::{Deserialize, Serialize}; diff --git a/crates/ecstore/src/set_disk.rs b/crates/ecstore/src/set_disk.rs index 784efe53c..88e9783be 100644 --- a/crates/ecstore/src/set_disk.rs +++ b/crates/ecstore/src/set_disk.rs @@ -52,8 +52,8 @@ use crate::{ event_notification::{EventArgs, send_event}, global::{GLOBAL_LOCAL_DISK_MAP, GLOBAL_LOCAL_DISK_SET_DRIVES, get_global_deployment_id, is_dist_erasure}, store_api::{ - BucketOperations, CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectsV2Info, - ListOperations, MultipartOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, PutObjReader, + CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectsV2Info, ListOperations, + MultipartOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, PutObjReader, }, store_init::load_format_erasure, }; @@ -86,8 +86,8 @@ use rustfs_object_capacity::capacity_scope::{ }; use rustfs_s3_types::EventName; use rustfs_storage_api::{ - BucketInfo, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, MultipartInfo, - MultipartUploadResult, PartInfo, + BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, + MultipartInfo, MultipartUploadResult, PartInfo, }; use rustfs_utils::http::headers::AMZ_OBJECT_TAGGING; use rustfs_utils::http::headers::AMZ_STORAGE_CLASS; @@ -1667,6 +1667,8 @@ impl NamespaceLocking for SetDisks { #[async_trait::async_trait] impl BucketOperations for SetDisks { + type Error = Error; + #[tracing::instrument(skip(self))] async fn make_bucket(&self, _bucket: &str, _opts: &MakeBucketOptions) -> Result<()> { unimplemented!() diff --git a/crates/ecstore/src/sets.rs b/crates/ecstore/src/sets.rs index faa993842..e5a79844a 100644 --- a/crates/ecstore/src/sets.rs +++ b/crates/ecstore/src/sets.rs @@ -28,9 +28,9 @@ use crate::{ global::{GLOBAL_LOCAL_DISK_SET_DRIVES, get_global_lock_clients, is_dist_erasure}, set_disk::SetDisks, store_api::{ - BucketOperations, CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectVersionsInfo, - ListObjectsV2Info, ListOperations, MultipartOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, - ObjectOptions, ObjectToDelete, PutObjReader, + CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectVersionsInfo, ListObjectsV2Info, + ListOperations, MultipartOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, ObjectOptions, + ObjectToDelete, PutObjReader, }, store_init::{check_format_erasure_values, get_format_erasure_in_quorum, load_format_erasure_all, save_format_file}, }; @@ -49,8 +49,8 @@ use rustfs_lock::NamespaceLockWrapper; use rustfs_lock::client::LockClient; use rustfs_madmin::heal_commands::{HealDriveInfo, HealResultItem}; use rustfs_storage_api::{ - BucketInfo, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, MultipartInfo, - MultipartUploadResult, PartInfo, + BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, + MultipartInfo, MultipartUploadResult, PartInfo, }; use rustfs_utils::{crc_hash, path::path_join_buf, sip_hash}; use std::{collections::HashMap, sync::Arc}; @@ -423,6 +423,8 @@ impl ObjectIO for Sets { #[async_trait::async_trait] impl BucketOperations for Sets { + type Error = Error; + #[tracing::instrument(skip(self))] async fn make_bucket(&self, _bucket: &str, _opts: &MakeBucketOptions) -> Result<()> { unimplemented!() diff --git a/crates/ecstore/src/store.rs b/crates/ecstore/src/store.rs index 737aa608f..5bf6e2c03 100644 --- a/crates/ecstore/src/store.rs +++ b/crates/ecstore/src/store.rs @@ -63,9 +63,8 @@ use crate::{ rpc::S3PeerSys, sets::Sets, store_api::{ - BucketOperations, CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectsV2Info, - ListOperations, MultipartOperations, NamespaceLocking, ObjectInfo, ObjectOperations, ObjectOptions, ObjectToDelete, - PutObjReader, + CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, HealOperations, ListObjectsV2Info, ListOperations, + MultipartOperations, NamespaceLocking, ObjectInfo, ObjectOperations, ObjectOptions, ObjectToDelete, PutObjReader, }, store_init, }; @@ -80,8 +79,8 @@ use rustfs_filemeta::FileInfo; use rustfs_lock::{LocalClient, LockClient, NamespaceLockWrapper}; use rustfs_madmin::heal_commands::HealResultItem; use rustfs_storage_api::{ - BucketInfo, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, MultipartInfo, - MultipartUploadResult, PartInfo, + BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, + MultipartInfo, MultipartUploadResult, PartInfo, }; use rustfs_utils::path::{decode_dir_object, encode_dir_object, path_join_buf}; use s3s::dto::{BucketVersioningStatus, ObjectLockConfiguration, ObjectLockEnabled, VersioningConfiguration}; @@ -398,6 +397,8 @@ lazy_static! { #[async_trait::async_trait] impl BucketOperations for ECStore { + type Error = Error; + #[instrument(skip(self))] async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<()> { self.handle_make_bucket(bucket, opts).await diff --git a/crates/ecstore/src/store_api/traits.rs b/crates/ecstore/src/store_api/traits.rs index f9b1b0d68..e5eb2de23 100644 --- a/crates/ecstore/src/store_api/traits.rs +++ b/crates/ecstore/src/store_api/traits.rs @@ -1,8 +1,5 @@ use super::*; -use rustfs_storage_api::{ - BucketInfo, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions, MultipartInfo, - MultipartUploadResult, PartInfo, -}; +use rustfs_storage_api::{ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo}; #[async_trait::async_trait] pub trait ObjectIO: Send + Sync + Debug + 'static { @@ -18,15 +15,6 @@ pub trait ObjectIO: Send + Sync + Debug + 'static { async fn put_object(&self, bucket: &str, object: &str, data: &mut PutObjReader, opts: &ObjectOptions) -> Result; } -/// Bucket-level storage operations. -#[async_trait::async_trait] -pub trait BucketOperations: Send + Sync + Debug { - async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<()>; - async fn get_bucket_info(&self, bucket: &str, opts: &BucketOptions) -> Result; - async fn list_bucket(&self, opts: &BucketOptions) -> Result>; - async fn delete_bucket(&self, bucket: &str, opts: &DeleteBucketOptions) -> Result<()>; -} - /// Object-level storage operations (beyond basic I/O in ObjectIO). #[async_trait::async_trait] #[allow(clippy::too_many_arguments)] diff --git a/crates/heal/src/heal/storage.rs b/crates/heal/src/heal/storage.rs index 40d708e9f..a0eb8df58 100644 --- a/crates/heal/src/heal/storage.rs +++ b/crates/heal/src/heal/storage.rs @@ -19,10 +19,10 @@ use rustfs_ecstore::{ disk::{DiskStore, endpoint::Endpoint}, error::StorageError, store::ECStore, - store_api::{BucketOperations, HealOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions}, + store_api::{HealOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions}, }; use rustfs_madmin::heal_commands::HealResultItem; -use rustfs_storage_api::{BucketInfo, DiskSetSelector, StorageAdminApi}; +use rustfs_storage_api::{BucketInfo, BucketOperations, DiskSetSelector, StorageAdminApi}; use std::sync::Arc; use tracing::{debug, error, warn}; diff --git a/crates/heal/tests/heal_integration_test.rs b/crates/heal/tests/heal_integration_test.rs index 17222eb06..551e64bf6 100644 --- a/crates/heal/tests/heal_integration_test.rs +++ b/crates/heal/tests/heal_integration_test.rs @@ -18,13 +18,14 @@ use rustfs_ecstore::{ disk::endpoint::Endpoint, endpoints::{EndpointServerPools, Endpoints, PoolEndpoints}, store::ECStore, - store_api::{BucketOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, + store_api::{ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, }; use rustfs_heal::heal::{ manager::{HealConfig, HealManager}, storage::{ECStoreHealStorage, HealStorageAPI}, task::{HealOptions, HealPriority, HealRequest, HealTaskStatus, HealType}, }; +use rustfs_storage_api::BucketOperations; use serial_test::serial; use std::{ path::{Path, PathBuf}, diff --git a/crates/obs/src/metrics/stats_collector.rs b/crates/obs/src/metrics/stats_collector.rs index 77e7b5122..5e8abb389 100644 --- a/crates/obs/src/metrics/stats_collector.rs +++ b/crates/obs/src/metrics/stats_collector.rs @@ -36,11 +36,10 @@ use rustfs_ecstore::data_usage::load_data_usage_from_backend; use rustfs_ecstore::global::get_global_bucket_monitor; use rustfs_ecstore::pools::{get_total_usable_capacity, get_total_usable_capacity_free}; use rustfs_ecstore::resolve_object_store_handle; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_iam::{get_global_iam_sys, oidc::oidc_plugin_authn_metrics_snapshot}; use rustfs_io_metrics::internode_metrics::global_internode_metrics; use rustfs_io_metrics::{ProcessStatusSnapshot, snapshot_process_resource_and_system}; -use rustfs_storage_api::{BucketOptions, StorageAdminApi}; +use rustfs_storage_api::{BucketOperations, BucketOptions, StorageAdminApi}; use std::collections::HashMap; use std::time::Duration; use sysinfo::{Networks, System}; diff --git a/crates/protocols/src/swift/account.rs b/crates/protocols/src/swift/account.rs index 0572bee2e..7ec08defe 100644 --- a/crates/protocols/src/swift/account.rs +++ b/crates/protocols/src/swift/account.rs @@ -17,8 +17,7 @@ use super::{SwiftError, SwiftResult}; use rustfs_credentials::Credentials; use rustfs_ecstore::resolve_object_store_handle; -use rustfs_ecstore::store_api::BucketOperations; -use rustfs_storage_api::MakeBucketOptions; +use rustfs_storage_api::{BucketOperations, MakeBucketOptions}; use s3s::dto::{Tag, Tagging}; use sha2::{Digest, Sha256}; use std::collections::HashMap; diff --git a/crates/protocols/src/swift/container.rs b/crates/protocols/src/swift/container.rs index dbd2e2e7f..f5ce62035 100644 --- a/crates/protocols/src/swift/container.rs +++ b/crates/protocols/src/swift/container.rs @@ -21,8 +21,8 @@ use super::types::Container; use super::{SwiftError, SwiftResult}; use rustfs_credentials::Credentials; use rustfs_ecstore::resolve_object_store_handle; -use rustfs_ecstore::store_api::{BucketOperations, ListOperations}; -use rustfs_storage_api::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions}; +use rustfs_ecstore::store_api::ListOperations; +use rustfs_storage_api::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions}; use s3s::dto::{Tag, Tagging}; use sha2::{Digest, Sha256}; use tracing::{debug, error}; diff --git a/crates/protocols/src/swift/object.rs b/crates/protocols/src/swift/object.rs index 76171149f..6f0478062 100644 --- a/crates/protocols/src/swift/object.rs +++ b/crates/protocols/src/swift/object.rs @@ -55,9 +55,9 @@ use super::{SwiftError, SwiftResult}; use axum::http::HeaderMap; use rustfs_credentials::Credentials; use rustfs_ecstore::resolve_object_store_handle; -use rustfs_ecstore::store_api::{BucketOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}; +use rustfs_ecstore::store_api::{ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}; use rustfs_rio::HashReader; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use std::collections::HashMap; use tracing::debug; use tracing::error; diff --git a/crates/scanner/src/scanner.rs b/crates/scanner/src/scanner.rs index 81c034e42..c14069adf 100644 --- a/crates/scanner/src/scanner.rs +++ b/crates/scanner/src/scanner.rs @@ -45,8 +45,8 @@ use rustfs_ecstore::disk::RUSTFS_META_BUCKET; use rustfs_ecstore::error::Error as EcstoreError; use rustfs_ecstore::global::is_erasure_sd; use rustfs_ecstore::store::ECStore; -use rustfs_ecstore::store_api::{BucketOperations, NamespaceLocking as _, ObjectIO}; -use rustfs_storage_api::BucketOptions; +use rustfs_ecstore::store_api::{NamespaceLocking as _, ObjectIO}; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use serde::{Deserialize, Serialize}; use tokio::sync::mpsc; use tokio::time::{Duration, Instant}; diff --git a/crates/scanner/src/scanner_io.rs b/crates/scanner/src/scanner_io.rs index 9b1838252..a020cc9b0 100644 --- a/crates/scanner/src/scanner_io.rs +++ b/crates/scanner/src/scanner_io.rs @@ -41,10 +41,10 @@ use rustfs_ecstore::error::{Error, StorageError}; use rustfs_ecstore::global::GLOBAL_TierConfigMgr; use rustfs_ecstore::resolve_object_store_handle; use rustfs_ecstore::set_disk::SetDisks; -use rustfs_ecstore::store_api::{BucketOperations, ObjectIO, ObjectInfo}; +use rustfs_ecstore::store_api::{ObjectIO, ObjectInfo}; use rustfs_ecstore::{error::Result, store::ECStore}; use rustfs_filemeta::FileMeta; -use rustfs_storage_api::{BucketInfo, BucketOptions, DiskSetSelector, StorageAdminApi}; +use rustfs_storage_api::{BucketInfo, BucketOperations, BucketOptions, DiskSetSelector, StorageAdminApi}; use rustfs_utils::path::path_join_buf; use s3s::dto::{BucketLifecycleConfiguration, ReplicationConfiguration}; use std::collections::{HashMap, HashSet}; diff --git a/crates/scanner/tests/lifecycle_integration_test.rs b/crates/scanner/tests/lifecycle_integration_test.rs index a78b68ba1..c920e8e1f 100644 --- a/crates/scanner/tests/lifecycle_integration_test.rs +++ b/crates/scanner/tests/lifecycle_integration_test.rs @@ -28,7 +28,7 @@ use rustfs_ecstore::{ global::GLOBAL_TierConfigMgr, pools::path2_bucket_object_with_base_path, store::ECStore, - store_api::{BucketOperations, ListOperations, MultipartOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, + store_api::{ListOperations, MultipartOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, tier::{ tier_config::{TierConfig, TierMinIO, TierType}, warm_backend::{WarmBackend, WarmBackendGetOpts, build_transition_put_options}, @@ -38,7 +38,7 @@ use rustfs_filemeta::FileMeta; use rustfs_scanner::scanner::init_data_scanner; use rustfs_scanner::scanner_folder::ScannerItem; use rustfs_scanner::scanner_io::ScannerIODisk; -use rustfs_storage_api::MakeBucketOptions; +use rustfs_storage_api::{BucketOperations, MakeBucketOptions}; use rustfs_utils::path::path_join_buf; use s3s::dto::RestoreRequest; use serial_test::serial; diff --git a/crates/storage-api/src/bucket.rs b/crates/storage-api/src/bucket.rs index b25214f27..639f57e0c 100644 --- a/crates/storage-api/src/bucket.rs +++ b/crates/storage-api/src/bucket.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt::Debug; + use serde::{Deserialize, Serialize}; use time::OffsetDateTime; @@ -56,6 +58,17 @@ pub struct BucketInfo { pub object_locking: bool, } +/// Bucket-level storage operations. +#[async_trait::async_trait] +pub trait BucketOperations: Send + Sync + Debug { + type Error: std::error::Error + Send + Sync + 'static; + + async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<(), Self::Error>; + async fn get_bucket_info(&self, bucket: &str, opts: &BucketOptions) -> Result; + async fn list_bucket(&self, opts: &BucketOptions) -> Result, Self::Error>; + async fn delete_bucket(&self, bucket: &str, opts: &DeleteBucketOptions) -> Result<(), Self::Error>; +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/storage-api/src/lib.rs b/crates/storage-api/src/lib.rs index b74f9014e..313e12b5b 100644 --- a/crates/storage-api/src/lib.rs +++ b/crates/storage-api/src/lib.rs @@ -20,6 +20,6 @@ pub mod error; pub mod multipart; pub use admin::{DiskSetSelector, StorageAdminApi}; -pub use bucket::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp}; +pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp}; pub use error::{StorageErrorCode, StorageResult}; pub use multipart::{ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo}; diff --git a/docs/architecture/crate-boundaries.md b/docs/architecture/crate-boundaries.md index f2825c6d3..b81afc036 100644 --- a/docs/architecture/crate-boundaries.md +++ b/docs/architecture/crate-boundaries.md @@ -91,7 +91,7 @@ compatibility coverage from silently drifting during cleanup PRs. Required `rustfs-storage-api` public re-exports: - `pub use admin::{DiskSetSelector, StorageAdminApi};` -- `pub use bucket::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};` +- `pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};` - `pub use error::{StorageErrorCode, StorageResult};` - `pub use multipart::{ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};` diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index 7c75b2f85..72a8bcef1 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-storage-object-contracts-cleanup` -- Baseline: `origin/main` at `2ff69ae21cad69eaf7d5969eb5267e6e974ef8c6` +- Branch: `overtrue/arch-bucket-operations-contract` +- Baseline: `origin/main` at `1830911973f882e30a1de18a5ff7d2ab669d67dc` - PR type for this branch: `api-extraction` - Runtime behavior changes: no external behavior change expected. -- Rust code changes: move multipart list/result DTO contracts from ECStore +- Rust code changes: move the `BucketOperations` contract from ECStore `store_api` into `rustfs-storage-api` and migrate in-repo consumers to the shared contract path. -- CI/script changes: extend migration guards for the multipart DTO public - re-export and reject restoring the old ECStore-owned multipart DTO path. -- Docs changes: record the multipart DTO contract extraction slice. +- CI/script changes: extend migration guards for the bucket contract public + re-export and reject restoring the old ECStore-owned `BucketOperations` path. +- Docs changes: record the bucket operation contract extraction slice. ## Phase 0 Tasks @@ -518,6 +518,24 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block response tests, migration/layer guards, formatting, diff hygiene, Rust risk scan, and required three-expert review passed. +- [x] `API-014` Move bucket operation contract. + - Completed slice: move `BucketOperations` from ECStore `store_api` into + `rustfs-storage-api`, keep ECStore/Sets/SetDisks implementations in + ECStore, and migrate in-repo consumers to import the shared contract path. + - Acceptance: `rustfs-storage-api` exports the bucket operation contract, + in-repo consumers no longer use the old `rustfs_ecstore::store_api` path + for `BucketOperations`, and migration guards reject restoring the old + ECStore-owned definition or re-export. + - Must preserve: bucket create/delete/list/info behavior, object store + initialization, bucket metadata migration, Swift/admin/storage consumers, + and all storage hot paths. + - Risk defense: only the trait contract crosses into `rustfs-storage-api`; + ECStore errors, object contracts, list contracts, readers, lock handling, + and implementation bodies stay in ECStore. + - Verification: focused storage-api/ECStore/RustFS/downstream compile checks, + migration/layer guards, formatting, diff hygiene, Rust risk scan, and + required three-expert review passed. + ## Phase 8 Background Controller Tasks - [x] `BGC-001` Inventory background services. @@ -794,18 +812,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| -| Quality/architecture | passed | Multipart list/result DTOs now live in the storage contract crate, while ECStore keeps implementation-heavy object, reader, range, and complete-part types. | -| Migration preservation | passed | The slice moves DTO ownership and import paths only; multipart operation bodies, S3 response mapping logic, and storage hot paths are unchanged. | -| Testing/verification | passed | Focused storage-api/ECStore/RustFS compile checks, multipart response tests, migration/layer guards, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. | +| Quality/architecture | passed | `BucketOperations` now lives in the storage contract crate with an associated ECStore error type, while implementation bodies and storage-heavy contracts remain in ECStore. | +| Migration preservation | passed | The slice changes trait ownership and import paths only; bucket operation bodies, metadata migration flow, admin/Swift/storage callers, and storage hot paths are unchanged. | +| Testing/verification | passed | Focused storage-api/ECStore/RustFS/downstream compile checks, migration/layer guards, formatting, diff hygiene, Rust risk scan, and full `make pre-commit` passed. | ## Verification Notes -Passed on `2ff69ae21cad69eaf7d5969eb5267e6e974ef8c6`: +Passed on `1830911973f882e30a1de18a5ff7d2ab669d67dc`: - `cargo check -p rustfs-storage-api -p rustfs-ecstore`: passed. -- `cargo check -p rustfs`: passed. -- `cargo test -p rustfs --lib storage::s3_api::multipart --no-fail-fast`: - passed. +- `cargo check -p rustfs -p rustfs-heal -p rustfs-scanner -p rustfs-protocols -p rustfs-obs`: passed. - `./scripts/check_architecture_migration_rules.sh`: passed. - `./scripts/check_layer_dependencies.sh`: passed. - `cargo fmt --all --check`: passed. @@ -816,17 +832,16 @@ Passed on `2ff69ae21cad69eaf7d5969eb5267e6e974ef8c6`: Notes: -- This slice follows `rustfs/rustfs#3503` and keeps the old aggregate facade and - bucket DTO guards active. -- The shared multipart list/result DTOs are now owned by `rustfs-storage-api`; - ECStore keeps implementation-heavy object, reader, range, and complete-part - types. -- The slice does not move storage operation traits across crate boundaries or - alter multipart runtime behavior. +- This slice follows `rustfs/rustfs#3505` and keeps the old aggregate facade, + bucket DTO, multipart DTO, and bucket operation contract guards active. +- The shared `BucketOperations` contract is now owned by + `rustfs-storage-api`; ECStore keeps implementation-heavy object, list, + reader, lock, and storage error contracts. +- The slice does not alter bucket runtime behavior. ## Handoff Notes -- Storage multipart DTO contract cleanup is in progress on a branch current with +- Bucket operation contract cleanup is in progress on a branch current with `origin/main`. - After this lands, remaining storage work can continue by extracting only DTOs that have proven low implementation coupling. diff --git a/rustfs/src/admin/handlers/account_info.rs b/rustfs/src/admin/handlers/account_info.rs index bdc1ebc38..c819bbcbf 100644 --- a/rustfs/src/admin/handlers/account_info.rs +++ b/rustfs/src/admin/handlers/account_info.rs @@ -22,11 +22,10 @@ use hyper::{Method, StatusCode}; use matchit::Params; use rustfs_credentials::get_global_action_cred; use rustfs_ecstore::bucket::versioning_sys::BucketVersioningSys; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_policy::policy::BucketPolicy; use rustfs_policy::policy::default::DEFAULT_POLICIES; use rustfs_policy::policy::{Args, action::Action, action::S3Action}; -use rustfs_storage_api::{BucketOptions, StorageAdminApi}; +use rustfs_storage_api::{BucketOperations, BucketOptions, StorageAdminApi}; use s3s::header::CONTENT_TYPE; use s3s::{Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result, s3_error}; use serde::Serialize; diff --git a/rustfs/src/admin/handlers/bucket_meta.rs b/rustfs/src/admin/handlers/bucket_meta.rs index ab9e078fb..cdf94983e 100644 --- a/rustfs/src/admin/handlers/bucket_meta.rs +++ b/rustfs/src/admin/handlers/bucket_meta.rs @@ -38,13 +38,12 @@ use rustfs_ecstore::{ target::BucketTargets, }, error::StorageError, - store_api::BucketOperations, }; use rustfs_policy::policy::{ BucketPolicy, action::{Action, AdminAction}, }; -use rustfs_storage_api::{BucketOptions, MakeBucketOptions}; +use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions}; use rustfs_utils::path::{SLASH_SEPARATOR, path_join_buf}; use s3s::{ Body, S3Request, S3Response, S3Result, diff --git a/rustfs/src/admin/handlers/object_zip_download.rs b/rustfs/src/admin/handlers/object_zip_download.rs index cc2f54186..dcf1c7db9 100644 --- a/rustfs/src/admin/handlers/object_zip_download.rs +++ b/rustfs/src/admin/handlers/object_zip_download.rs @@ -33,10 +33,10 @@ use rustfs_config::MAX_ADMIN_REQUEST_BODY_SIZE; use rustfs_credentials::get_global_action_cred; use rustfs_ecstore::{ global::get_global_region, - store_api::{BucketOperations, ListOperations, ObjectIO, ObjectOperations, ObjectOptions}, + store_api::{ListOperations, ObjectIO, ObjectOperations, ObjectOptions}, }; use rustfs_policy::policy::action::{Action, S3Action}; -use rustfs_storage_api::bucket::BucketOptions; +use rustfs_storage_api::{BucketOperations, bucket::BucketOptions}; use rustfs_trusted_proxies::{ClientInfo, ValidationMode}; use rustfs_utils::{base64_decode_url_safe_no_pad, base64_encode_url_safe_no_pad}; use s3s::{Body, S3Request, S3Response, S3Result, dto::StreamingBlob, header::CONTENT_TYPE, s3_error}; diff --git a/rustfs/src/admin/handlers/rebalance.rs b/rustfs/src/admin/handlers/rebalance.rs index 42b4eeb51..8f063ae29 100644 --- a/rustfs/src/admin/handlers/rebalance.rs +++ b/rustfs/src/admin/handlers/rebalance.rs @@ -28,10 +28,9 @@ use rustfs_ecstore::{ error::StorageError, notification_sys::get_global_notification_sys, rebalance::{DiskStat, RebalSaveOpt, RebalanceCleanupWarnings, RebalanceMeta}, - store_api::BucketOperations, }; use rustfs_policy::policy::action::{Action, AdminAction}; -use rustfs_storage_api::{BucketOptions, StorageAdminApi}; +use rustfs_storage_api::{BucketOperations, BucketOptions, StorageAdminApi}; use s3s::{ Body, S3Request, S3Response, S3Result, header::{CONTENT_LENGTH, CONTENT_TYPE}, diff --git a/rustfs/src/admin/handlers/replication.rs b/rustfs/src/admin/handlers/replication.rs index fc40b2653..410794220 100644 --- a/rustfs/src/admin/handlers/replication.rs +++ b/rustfs/src/admin/handlers/replication.rs @@ -34,9 +34,8 @@ use rustfs_ecstore::bucket::replication::GLOBAL_REPLICATION_STATS; use rustfs_ecstore::bucket::target::BucketTarget; use rustfs_ecstore::error::StorageError; use rustfs_ecstore::global::global_rustfs_port; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_policy::policy::action::{Action, AdminAction}; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use s3s::header::CONTENT_TYPE; use s3s::{Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result, s3_error}; use std::collections::HashMap; diff --git a/rustfs/src/admin/handlers/site_replication.rs b/rustfs/src/admin/handlers/site_replication.rs index c89c4e1ef..85fd477e2 100644 --- a/rustfs/src/admin/handlers/site_replication.rs +++ b/rustfs/src/admin/handlers/site_replication.rs @@ -50,7 +50,6 @@ use rustfs_ecstore::bucket::versioning::VersioningApi; use rustfs_ecstore::config::com::{delete_config, read_config, save_config}; use rustfs_ecstore::error::Error as StorageError; use rustfs_ecstore::global::{get_global_deployment_id, get_global_endpoints_opt, get_global_region, global_rustfs_port}; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_iam::error::is_err_no_such_service_account; use rustfs_iam::store::{MappedPolicy, UserType}; use rustfs_iam::sys::{ @@ -71,7 +70,7 @@ use rustfs_policy::policy::{ }; use rustfs_signer::constants::UNSIGNED_PAYLOAD; use rustfs_signer::sign_v4; -use rustfs_storage_api::{BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp}; +use rustfs_storage_api::{BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp}; use rustfs_tls_runtime::{GlobalPublishedOutboundTlsState, load_global_outbound_tls_generation, load_global_outbound_tls_state}; use rustfs_utils::http::get_source_scheme; use rustls_pki_types::pem::PemObject; diff --git a/rustfs/src/admin/router.rs b/rustfs/src/admin/router.rs index 6aa2a5da1..73b8151df 100644 --- a/rustfs/src/admin/router.rs +++ b/rustfs/src/admin/router.rs @@ -62,14 +62,13 @@ use rustfs_ecstore::global::GLOBAL_BOOT_TIME; use rustfs_ecstore::global::{get_global_bucket_monitor, get_global_deployment_id, get_global_region}; use rustfs_ecstore::notification_sys::get_global_notification_sys; use rustfs_ecstore::rpc::PeerRestClient; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_filemeta::{ReplicationStatusType, ReplicationType}; use rustfs_madmin::utils::parse_duration; use rustfs_notify::{Event as NotificationEvent, notification_system}; use rustfs_policy::policy::action::{Action, S3Action}; use rustfs_s3_types::EventName; use rustfs_signer::pre_sign_v4; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_utils::http::{ SUFFIX_SOURCE_DELETEMARKER, SUFFIX_SOURCE_MTIME, SUFFIX_SOURCE_REPLICATION_CHECK, SUFFIX_SOURCE_REPLICATION_REQUEST, SUFFIX_SOURCE_VERSION_ID, get_source_scheme, insert_header, diff --git a/rustfs/src/app/bucket_usecase.rs b/rustfs/src/app/bucket_usecase.rs index 10743ec62..381c69d68 100644 --- a/rustfs/src/app/bucket_usecase.rs +++ b/rustfs/src/app/bucket_usecase.rs @@ -57,14 +57,14 @@ use rustfs_ecstore::client::object_api_utils::to_s3s_etag; use rustfs_ecstore::error::StorageError; use rustfs_ecstore::notification_sys::get_global_notification_sys; use rustfs_ecstore::store::ECStore; -use rustfs_ecstore::store_api::{BucketOperations, ListObjectVersionsInfo, ListObjectsV2Info, ListOperations, ObjectInfo}; +use rustfs_ecstore::store_api::{ListObjectVersionsInfo, ListObjectsV2Info, ListOperations, ObjectInfo}; use rustfs_madmin::{SITE_REPL_API_VERSION, SRBucketMeta}; use rustfs_policy::policy::{ action::{Action, S3Action}, {BucketPolicy, BucketPolicyArgs, Effect, Validator}, }; use rustfs_s3_ops::S3Operation; -use rustfs_storage_api::{BucketOptions, DeleteBucketOptions, MakeBucketOptions}; +use rustfs_storage_api::{BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions}; use rustfs_targets::{ EventName, arn::{ARN, TargetIDError}, diff --git a/rustfs/src/app/capacity_dirty_scope_test.rs b/rustfs/src/app/capacity_dirty_scope_test.rs index ea5148ff5..367c1c98f 100644 --- a/rustfs/src/app/capacity_dirty_scope_test.rs +++ b/rustfs/src/app/capacity_dirty_scope_test.rs @@ -18,10 +18,10 @@ use rustfs_ecstore::{ disk::endpoint::Endpoint, endpoints::{EndpointServerPools, Endpoints, PoolEndpoints}, store::ECStore, - store_api::{BucketOperations, HealOperations, ObjectIO, ObjectOptions, PutObjReader}, + store_api::{HealOperations, ObjectIO, ObjectOptions, PutObjReader}, }; use rustfs_object_capacity::capacity_manager::{HybridStrategyConfig, create_isolated_manager}; -use rustfs_storage_api::{BucketOptions, MakeBucketOptions}; +use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions}; use serial_test::serial; use std::{ collections::HashSet, diff --git a/rustfs/src/app/lifecycle_transition_api_test.rs b/rustfs/src/app/lifecycle_transition_api_test.rs index ead30cbd5..bae165eec 100644 --- a/rustfs/src/app/lifecycle_transition_api_test.rs +++ b/rustfs/src/app/lifecycle_transition_api_test.rs @@ -29,14 +29,14 @@ use rustfs_ecstore::{ endpoints::{EndpointServerPools, Endpoints, PoolEndpoints}, global::GLOBAL_TierConfigMgr, store::ECStore, - store_api::{BucketOperations, ListOperations, MultipartOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, + store_api::{ListOperations, MultipartOperations, ObjectIO, ObjectOperations, ObjectOptions, PutObjReader}, tier::{ tier_config::{TierConfig, TierType}, warm_backend::{WarmBackend, WarmBackendGetOpts}, }, }; use rustfs_object_capacity::capacity_manager::{HybridStrategyConfig, create_isolated_manager}; -use rustfs_storage_api::{BucketOptions, MakeBucketOptions}; +use rustfs_storage_api::{BucketOperations, BucketOptions, MakeBucketOptions}; use rustfs_utils::http::{SUFFIX_FORCE_DELETE, insert_header}; use s3s::{S3Request, dto::*}; use serial_test::serial; diff --git a/rustfs/src/embedded.rs b/rustfs/src/embedded.rs index a99817bf7..a25bfb171 100644 --- a/rustfs/src/embedded.rs +++ b/rustfs/src/embedded.rs @@ -66,11 +66,10 @@ use rustfs_ecstore::{ set_global_endpoints, store::ECStore, store::init_local_disks, - store_api::BucketOperations, update_erasure_type, }; use rustfs_obs::{init_obs, set_global_guard}; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_utils::net::parse_and_resolve_address; use rustls::crypto::aws_lc_rs::default_provider; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; diff --git a/rustfs/src/startup_services.rs b/rustfs/src/startup_services.rs index b6e858069..93538629a 100644 --- a/rustfs/src/startup_services.rs +++ b/rustfs/src/startup_services.rs @@ -38,7 +38,6 @@ use rustfs_ecstore::{ global::shutdown_background_services, notification_sys::new_global_notification_sys, store::ECStore, - store_api::BucketOperations, }; use rustfs_heal::{ create_ahm_services_cancel_token, heal::storage::ECStoreHealStorage, init_heal_manager, shutdown_ahm_services, @@ -46,7 +45,7 @@ use rustfs_heal::{ use rustfs_iam::init_oidc_sys; use rustfs_obs::init_metrics_runtime; use rustfs_scanner::init_data_scanner; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_utils::get_env_bool_with_aliases; use std::{ future::Future, diff --git a/rustfs/src/storage/access.rs b/rustfs/src/storage/access.rs index 3d975ea1c..fcae74326 100644 --- a/rustfs/src/storage/access.rs +++ b/rustfs/src/storage/access.rs @@ -24,13 +24,13 @@ use rustfs_ecstore::bucket::policy_sys::PolicySys; use rustfs_ecstore::error::{StorageError, is_err_bucket_not_found}; use rustfs_ecstore::resolve_object_store_handle; use rustfs_ecstore::store::ECStore; -use rustfs_ecstore::store_api::BucketOperations; use rustfs_iam::error::Error as IamError; use rustfs_policy::policy::action::{Action, AdminAction, S3Action}; use rustfs_policy::policy::{ Args, BucketPolicy, BucketPolicyArgs, bucket_policy_needs_existing_object_tag_for_args, bucket_policy_uses_existing_object_tag_conditions, }; +use rustfs_storage_api::BucketOperations; use rustfs_trusted_proxies::ClientInfo; use rustfs_utils::http::AMZ_OBJECT_LOCK_BYPASS_GOVERNANCE; use s3s::access::{S3Access, S3AccessContext}; diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 8926b0eaf..d6e71732a 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -40,11 +40,11 @@ use rustfs_ecstore::{ versioning_sys::BucketVersioningSys, }, error::{StorageError, is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found}, - store_api::{BucketOperations, ObjectLockRetentionOptions, ObjectOperations, ObjectOptions}, + store_api::{ObjectLockRetentionOptions, ObjectOperations, ObjectOptions}, }; use rustfs_io_metrics::record_s3_op; use rustfs_s3_ops::S3Operation; -use rustfs_storage_api::BucketOptions; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_targets::EventName; use rustfs_utils::http::headers::{ AMZ_OBJECT_LOCK_LEGAL_HOLD_LOWER, AMZ_OBJECT_LOCK_MODE_LOWER, AMZ_OBJECT_LOCK_RETAIN_UNTIL_DATE_LOWER, diff --git a/rustfs/src/storage/ecfs_extend.rs b/rustfs/src/storage/ecfs_extend.rs index e2c3e618c..8480ac449 100644 --- a/rustfs/src/storage/ecfs_extend.rs +++ b/rustfs/src/storage/ecfs_extend.rs @@ -25,8 +25,8 @@ use rustfs_ecstore::bucket::object_lock::objectlock_sys; use rustfs_ecstore::bucket::replication::ReplicationConfigurationExt; use rustfs_ecstore::error::StorageError; use rustfs_ecstore::resolve_object_store_handle; -use rustfs_ecstore::store_api::{BucketOperations, ObjectInfo, ObjectToDelete}; -use rustfs_storage_api::BucketOptions; +use rustfs_ecstore::store_api::{ObjectInfo, ObjectToDelete}; +use rustfs_storage_api::{BucketOperations, BucketOptions}; use rustfs_targets::EventName; use rustfs_targets::arn::{TargetID, TargetIDError}; use rustfs_utils::http::{ diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 8ef583e2b..4aff14f46 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -51,6 +51,7 @@ SOURCE_IDS_FILE="${TMP_DIR}/source_ids.txt" REGISTER_IDS_FILE="${TMP_DIR}/register_ids.txt" LEGACY_STORAGE_API_HITS_FILE="${TMP_DIR}/legacy_storage_api_hits.txt" STORE_API_BUCKET_DTO_REEXPORTS_FILE="${TMP_DIR}/store_api_bucket_dto_reexports.txt" +STORE_API_BUCKET_OPERATION_HITS_FILE="${TMP_DIR}/store_api_bucket_operation_hits.txt" STORE_API_MULTIPART_DTO_REEXPORTS_FILE="${TMP_DIR}/store_api_multipart_dto_reexports.txt" awk ' @@ -182,8 +183,8 @@ require_source_line \ "storage-api public admin contract re-export" require_source_line \ "crates/storage-api/src/lib.rs" \ - "pub use bucket::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};" \ - "storage-api public bucket DTO re-export" + "pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};" \ + "storage-api public bucket contract re-export" require_source_line \ "crates/storage-api/src/lib.rs" \ "pub use multipart::{ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};" \ @@ -212,6 +213,16 @@ if [[ -s "$STORE_API_BUCKET_DTO_REEXPORTS_FILE" ]]; then report_failure "old ecstore store_api bucket DTO re-export reintroduced: $(paste -sd '; ' "$STORE_API_BUCKET_DTO_REEXPORTS_FILE")" fi +( + cd "$ROOT_DIR" + rg -n --no-heading 'pub(?:\(crate\))? use rustfs_storage_api::\{[^}]*\bBucketOperations\b|pub trait BucketOperations\b' \ + crates/ecstore/src/store_api.rs crates/ecstore/src/store_api/traits.rs || true +) >"$STORE_API_BUCKET_OPERATION_HITS_FILE" + +if [[ -s "$STORE_API_BUCKET_OPERATION_HITS_FILE" ]]; then + report_failure "old ecstore store_api BucketOperations path reintroduced: $(paste -sd '; ' "$STORE_API_BUCKET_OPERATION_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --no-heading 'pub(?:\(crate\))? use rustfs_storage_api::\{[^}]*\b(?:ListMultipartsInfo|ListPartsInfo|MultipartInfo|MultipartUploadResult|PartInfo)\b|pub struct (?:ListMultipartsInfo|ListPartsInfo|MultipartInfo|MultipartUploadResult|PartInfo)\b' \