mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-27 16:48:58 +00:00
refactor: continue storage api contract cleanup (#3580)
* refactor: move delete object contracts to storage api * refactor: narrow store api compatibility exports * refactor: route table catalog test through storage compat
This commit is contained in:
Generated
+1
@@ -10065,6 +10065,7 @@ name = "rustfs-storage-api"
|
||||
version = "1.0.0-beta.8"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"rustfs-filemeta",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"time",
|
||||
|
||||
@@ -37,7 +37,7 @@ use crate::global::GLOBAL_LocalNodeName;
|
||||
use crate::global::{GLOBAL_LifecycleSys, GLOBAL_TierConfigMgr, get_global_deployment_id};
|
||||
use crate::set_disk::{MAX_PARTS_COUNT, RUSTFS_MULTIPART_BUCKET_KEY, RUSTFS_MULTIPART_OBJECT_KEY, SetDisks};
|
||||
use crate::store::ECStore;
|
||||
use crate::store_api::{GetObjectReader, ObjectInfo, ObjectOptions, ObjectToDelete};
|
||||
use crate::store_api::{GetObjectReader, ObjectInfo, ObjectOptions};
|
||||
use crate::tier::warm_backend::WarmBackendGetOpts;
|
||||
use async_channel::{Receiver as A_Receiver, Sender as A_Sender, bounded};
|
||||
use futures::Future;
|
||||
@@ -58,7 +58,9 @@ use rustfs_filemeta::{
|
||||
VersionPurgeStatusType, get_file_info, is_restored_object_on_disk,
|
||||
};
|
||||
use rustfs_s3_types::EventName;
|
||||
use rustfs_storage_api::{HTTPRangeSpec, ListOperations as _, MultipartOperations as _, ObjectOperations as _};
|
||||
use rustfs_storage_api::{
|
||||
DeletedObject, HTTPRangeSpec, ListOperations as _, MultipartOperations as _, ObjectOperations as _, ObjectToDelete,
|
||||
};
|
||||
use rustfs_utils::{get_env_i64, get_env_usize, path::encode_dir_object, string::strings_has_prefix_fold};
|
||||
use s3s::dto::{
|
||||
BucketLifecycleConfiguration, DefaultRetention, ExpirationStatus, ReplicationConfiguration, RestoreRequest,
|
||||
@@ -2692,9 +2694,9 @@ pub async fn apply_expiry_rule(event: &lifecycle::Event, src: &LcEventSrc, oi: &
|
||||
expiry_state.enqueue_by_days(oi, event, src).await
|
||||
}
|
||||
|
||||
fn lifecycle_deleted_object(oi: &ObjectInfo, dobj: &ObjectInfo) -> crate::store_api::DeletedObject {
|
||||
fn lifecycle_deleted_object(oi: &ObjectInfo, dobj: &ObjectInfo) -> DeletedObject {
|
||||
if dobj.delete_marker {
|
||||
return crate::store_api::DeletedObject {
|
||||
return DeletedObject {
|
||||
object_name: oi.name.clone(),
|
||||
delete_marker: true,
|
||||
delete_marker_version_id: dobj.version_id,
|
||||
@@ -2704,7 +2706,7 @@ fn lifecycle_deleted_object(oi: &ObjectInfo, dobj: &ObjectInfo) -> crate::store_
|
||||
}
|
||||
|
||||
if oi.delete_marker && oi.version_id.is_some() {
|
||||
return crate::store_api::DeletedObject {
|
||||
return DeletedObject {
|
||||
object_name: oi.name.clone(),
|
||||
delete_marker: false,
|
||||
delete_marker_version_id: oi.version_id,
|
||||
@@ -2713,7 +2715,7 @@ fn lifecycle_deleted_object(oi: &ObjectInfo, dobj: &ObjectInfo) -> crate::store_
|
||||
};
|
||||
}
|
||||
|
||||
crate::store_api::DeletedObject {
|
||||
DeletedObject {
|
||||
object_name: oi.name.clone(),
|
||||
delete_marker: false,
|
||||
version_id: oi.version_id,
|
||||
|
||||
@@ -42,6 +42,7 @@ use rustfs_filemeta::VersionPurgeStatusType;
|
||||
use rustfs_filemeta::replication_statuses_map;
|
||||
use rustfs_filemeta::version_purge_statuses_map;
|
||||
use rustfs_filemeta::{REPLICATE_EXISTING, REPLICATE_HEAL, REPLICATE_HEAL_DELETE};
|
||||
use rustfs_storage_api::DeletedObject;
|
||||
use rustfs_utils::http::{SUFFIX_REPLICATION_TIMESTAMP, get_str};
|
||||
use std::any::Any;
|
||||
use std::sync::Arc;
|
||||
@@ -838,7 +839,7 @@ impl<S: ReplicationStorage> ReplicationPool<S> {
|
||||
// get_object_info here because the delete-marker or version may
|
||||
// already be absent from the local store — that is expected.
|
||||
let dv = DeletedObjectReplicationInfo {
|
||||
delete_object: crate::store_api::DeletedObject {
|
||||
delete_object: DeletedObject {
|
||||
object_name: entry.object.clone(),
|
||||
version_id: entry.version_id,
|
||||
delete_marker_version_id: entry.delete_marker_version_id,
|
||||
@@ -1577,7 +1578,7 @@ pub async fn queue_replication_heal_internal(
|
||||
};
|
||||
|
||||
let dv = DeletedObjectReplicationInfo {
|
||||
delete_object: crate::store_api::DeletedObject {
|
||||
delete_object: DeletedObject {
|
||||
object_name: roi.name.clone(),
|
||||
delete_marker_version_id: dm_version_id,
|
||||
version_id,
|
||||
|
||||
@@ -33,10 +33,7 @@ use crate::global::GLOBAL_LocalNodeName;
|
||||
use crate::global::get_global_bucket_monitor;
|
||||
use crate::resolve_object_store_handle;
|
||||
use crate::set_disk::get_lock_acquire_timeout;
|
||||
use crate::store_api::{
|
||||
DeletedObject, ListOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, ObjectOptions, ObjectToDelete,
|
||||
WalkOptions,
|
||||
};
|
||||
use crate::store_api::{ListOperations, NamespaceLocking, ObjectIO, ObjectInfo, ObjectOperations, ObjectOptions, WalkOptions};
|
||||
use aws_sdk_s3::error::{ProvideErrorMetadata, SdkError};
|
||||
use aws_sdk_s3::operation::head_object::{HeadObjectError, HeadObjectOutput};
|
||||
use aws_sdk_s3::primitives::ByteStream;
|
||||
@@ -61,7 +58,7 @@ use rustfs_filemeta::{
|
||||
get_replication_state, parse_replicate_decision, replication_statuses_map, target_reset_header, version_purge_statuses_map,
|
||||
};
|
||||
use rustfs_s3_types::EventName;
|
||||
use rustfs_storage_api::HTTPRangeSpec;
|
||||
use rustfs_storage_api::{DeletedObject, HTTPRangeSpec, ObjectToDelete};
|
||||
use rustfs_utils::http::{
|
||||
AMZ_BUCKET_REPLICATION_STATUS, AMZ_OBJECT_TAGGING, AMZ_TAGGING_DIRECTIVE, CONTENT_ENCODING, HeaderExt as _,
|
||||
SSEC_ALGORITHM_HEADER, SSEC_KEY_HEADER, SSEC_KEY_MD5_HEADER, SUFFIX_OBJECTLOCK_LEGALHOLD_TIMESTAMP,
|
||||
|
||||
@@ -25,10 +25,10 @@ use crate::bucket::replication::{DeletedObjectReplicationInfo, check_replicate_d
|
||||
use crate::bucket::versioning::VersioningApi;
|
||||
use crate::bucket::versioning_sys::BucketVersioningSys;
|
||||
use crate::store::ECStore;
|
||||
use crate::store_api::{ObjectOptions, ObjectToDelete};
|
||||
use crate::store_api::ObjectOptions;
|
||||
use rustfs_filemeta::{REPLICATE_INCOMING_DELETE, ReplicationState, version_purge_statuses_map};
|
||||
use rustfs_lock::MAX_DELETE_LIST;
|
||||
use rustfs_storage_api::ObjectOperations as _;
|
||||
use rustfs_storage_api::{ObjectOperations as _, ObjectToDelete};
|
||||
|
||||
fn lifecycle_version_delete_replication_state(
|
||||
replicate_decision_str: String,
|
||||
|
||||
@@ -34,8 +34,8 @@ use crate::error::{Error, Result, is_err_version_not_found};
|
||||
use crate::error::{GenericError, ObjectApiError, is_err_object_not_found};
|
||||
use crate::global::{GLOBAL_LocalNodeName, GLOBAL_TierConfigMgr};
|
||||
use crate::store_api::ListObjectVersionsInfo;
|
||||
use crate::store_api::ObjectOptions;
|
||||
use crate::store_api::{ObjectInfoOrErr, WalkOptions};
|
||||
use crate::store_api::{ObjectOptions, ObjectToDelete};
|
||||
use crate::{
|
||||
bucket::lifecycle::bucket_lifecycle_ops::{
|
||||
LifecycleOps, gen_transition_objname, get_transitioned_object_reader, put_restore_opts,
|
||||
@@ -51,10 +51,7 @@ use crate::{
|
||||
// event::name::EventName,
|
||||
event_notification::{EventArgs, send_event},
|
||||
global::{GLOBAL_LOCAL_DISK_MAP, GLOBAL_LOCAL_DISK_SET_DRIVES, get_global_deployment_id, is_dist_erasure},
|
||||
store_api::{
|
||||
DeletedObject, GetObjectReader, ListObjectsV2Info, MultipartOperations, ObjectIO, ObjectInfo, ObjectOperations,
|
||||
PutObjReader,
|
||||
},
|
||||
store_api::{GetObjectReader, ListObjectsV2Info, MultipartOperations, ObjectIO, ObjectInfo, ObjectOperations, PutObjReader},
|
||||
store_init::load_format_erasure,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
@@ -87,8 +84,8 @@ use rustfs_object_capacity::capacity_scope::{
|
||||
use rustfs_s3_types::EventName;
|
||||
use rustfs_storage_api::HTTPRangeSpec;
|
||||
use rustfs_storage_api::{
|
||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo,
|
||||
MakeBucketOptions, MultipartInfo, MultipartUploadResult, PartInfo,
|
||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, ListMultipartsInfo,
|
||||
ListPartsInfo, MakeBucketOptions, MultipartInfo, MultipartUploadResult, ObjectToDelete, PartInfo,
|
||||
};
|
||||
use rustfs_storage_api::{MultipartOperations as _, NamespaceLocking as _, ObjectIO as _, ObjectOperations as _};
|
||||
use rustfs_utils::http::headers::AMZ_OBJECT_TAGGING;
|
||||
|
||||
@@ -27,10 +27,7 @@ use crate::{
|
||||
error::StorageError,
|
||||
global::{GLOBAL_LOCAL_DISK_SET_DRIVES, get_global_lock_clients, is_dist_erasure},
|
||||
set_disk::SetDisks,
|
||||
store_api::{
|
||||
DeletedObject, GetObjectReader, ListObjectVersionsInfo, ListObjectsV2Info, ObjectInfo, ObjectOptions, ObjectToDelete,
|
||||
PutObjReader,
|
||||
},
|
||||
store_api::{GetObjectReader, ListObjectVersionsInfo, ListObjectsV2Info, ObjectInfo, ObjectOptions, PutObjReader},
|
||||
store_init::{check_format_erasure_values, get_format_erasure_in_quorum, load_format_erasure_all, save_format_file},
|
||||
};
|
||||
use futures::{
|
||||
@@ -50,8 +47,8 @@ use rustfs_madmin::heal_commands::{HealDriveInfo, HealResultItem};
|
||||
use rustfs_storage_api::CompletePart;
|
||||
use rustfs_storage_api::HTTPRangeSpec;
|
||||
use rustfs_storage_api::{
|
||||
BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo, MakeBucketOptions,
|
||||
MultipartInfo, MultipartUploadResult, PartInfo,
|
||||
BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, DeletedObject, ListMultipartsInfo, ListPartsInfo,
|
||||
MakeBucketOptions, MultipartInfo, MultipartUploadResult, ObjectToDelete, PartInfo,
|
||||
};
|
||||
use rustfs_storage_api::{ObjectIO as _, ObjectOperations as _};
|
||||
use rustfs_utils::{crc_hash, path::path_join_buf, sip_hash};
|
||||
|
||||
@@ -62,7 +62,7 @@ use crate::{
|
||||
endpoints::EndpointServerPools,
|
||||
rpc::S3PeerSys,
|
||||
sets::Sets,
|
||||
store_api::{DeletedObject, GetObjectReader, ListObjectsV2Info, ObjectInfo, ObjectOptions, ObjectToDelete, PutObjReader},
|
||||
store_api::{GetObjectReader, ListObjectsV2Info, ObjectInfo, ObjectOptions, PutObjReader},
|
||||
store_init,
|
||||
};
|
||||
use futures::future::join_all;
|
||||
@@ -77,8 +77,8 @@ use rustfs_lock::{LocalClient, LockClient, NamespaceLockWrapper};
|
||||
use rustfs_madmin::heal_commands::HealResultItem;
|
||||
use rustfs_storage_api::HTTPRangeSpec;
|
||||
use rustfs_storage_api::{
|
||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, ListMultipartsInfo, ListPartsInfo,
|
||||
MakeBucketOptions, MultipartInfo, MultipartUploadResult, PartInfo,
|
||||
BucketInfo, BucketOperations, BucketOptions, CompletePart, DeleteBucketOptions, DeletedObject, ListMultipartsInfo,
|
||||
ListPartsInfo, MakeBucketOptions, MultipartInfo, MultipartUploadResult, ObjectToDelete, PartInfo,
|
||||
};
|
||||
use rustfs_utils::path::{decode_dir_object, encode_dir_object, path_join_buf};
|
||||
use s3s::dto::{BucketVersioningStatus, ObjectLockConfiguration, ObjectLockEnabled, VersioningConfiguration};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use super::*;
|
||||
use rustfs_storage_api::{CompletePart, ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};
|
||||
use rustfs_storage_api::{
|
||||
CompletePart, DeletedObject, ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, ObjectToDelete,
|
||||
PartInfo,
|
||||
};
|
||||
|
||||
pub trait ObjectIO:
|
||||
rustfs_storage_api::ObjectIO<
|
||||
|
||||
@@ -9,6 +9,8 @@ pub type ListObjectsV2Info = rustfs_storage_api::ListObjectsV2Info<ObjectInfo>;
|
||||
pub type ListObjectVersionsInfo = rustfs_storage_api::ListObjectVersionsInfo<ObjectInfo>;
|
||||
pub type ObjectInfoOrErr = rustfs_storage_api::ObjectInfoOrErr<ObjectInfo, Error>;
|
||||
pub type WalkOptions = rustfs_storage_api::WalkOptions<WalkFilter>;
|
||||
pub type ObjectToDelete = rustfs_storage_api::ObjectToDelete;
|
||||
pub type DeletedObject = rustfs_storage_api::DeletedObject;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ObjectOptions {
|
||||
@@ -714,59 +716,6 @@ fn versions_after_marker(file_infos: &rustfs_filemeta::FileInfoVersions, marker:
|
||||
.unwrap_or(&file_infos.versions)
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ObjectToDelete {
|
||||
pub object_name: String,
|
||||
pub version_id: Option<Uuid>,
|
||||
pub delete_marker_replication_status: Option<String>,
|
||||
pub version_purge_status: Option<VersionPurgeStatusType>,
|
||||
pub version_purge_statuses: Option<String>,
|
||||
pub replicate_decision_str: Option<String>,
|
||||
}
|
||||
|
||||
impl ObjectToDelete {
|
||||
pub fn replication_state(&self) -> ReplicationState {
|
||||
ReplicationState {
|
||||
replication_status_internal: self.delete_marker_replication_status.clone(),
|
||||
version_purge_status_internal: self.version_purge_statuses.clone(),
|
||||
replicate_decision_str: self.replicate_decision_str.clone().unwrap_or_default(),
|
||||
targets: replication_statuses_map(self.delete_marker_replication_status.as_deref().unwrap_or_default()),
|
||||
purge_targets: version_purge_statuses_map(self.version_purge_statuses.as_deref().unwrap_or_default()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DeletedObject {
|
||||
pub delete_marker: bool,
|
||||
pub delete_marker_version_id: Option<Uuid>,
|
||||
pub object_name: String,
|
||||
pub version_id: Option<Uuid>,
|
||||
// MTime of DeleteMarker on source that needs to be propagated to replica
|
||||
pub delete_marker_mtime: Option<OffsetDateTime>,
|
||||
// to support delete marker replication
|
||||
pub replication_state: Option<ReplicationState>,
|
||||
pub found: bool,
|
||||
pub force_delete: bool,
|
||||
}
|
||||
|
||||
impl DeletedObject {
|
||||
pub fn version_purge_status(&self) -> VersionPurgeStatusType {
|
||||
self.replication_state
|
||||
.as_ref()
|
||||
.map(|v| v.composite_version_purge_status())
|
||||
.unwrap_or(VersionPurgeStatusType::Empty)
|
||||
}
|
||||
|
||||
pub fn delete_marker_replication_status(&self) -> ReplicationStatusType {
|
||||
self.replication_state
|
||||
.as_ref()
|
||||
.map(|v| v.composite_replication_status())
|
||||
.unwrap_or(ReplicationStatusType::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
type WalkFilter = fn(&FileInfo) -> bool;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub(crate) mod ecstore {
|
||||
pub(crate) use rustfs_ecstore::{data_usage, disk, error, global, store, store_api};
|
||||
pub(crate) use rustfs_ecstore::{data_usage, disk, error, global, store};
|
||||
|
||||
pub(crate) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{ObjectInfo, ObjectOptions, PutObjReader};
|
||||
}
|
||||
}
|
||||
pub(crate) use self::ecstore::{
|
||||
data_usage::DATA_USAGE_CACHE_NAME,
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
// limitations under the License.
|
||||
|
||||
mod ecstore {
|
||||
pub(super) use rustfs_ecstore::store_api;
|
||||
pub(super) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{ObjectInfo, ObjectOptions};
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) type IamObjectInfo = ecstore::store_api::ObjectInfo;
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub(crate) mod ecstore {
|
||||
pub(crate) use rustfs_ecstore::{config, global, store_api};
|
||||
pub(crate) use rustfs_ecstore::{config, global};
|
||||
|
||||
pub(crate) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::ObjectInfo;
|
||||
}
|
||||
}
|
||||
|
||||
pub type NotifyObjectInfo = ecstore::store_api::ObjectInfo;
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
mod ecstore {
|
||||
pub(super) use rustfs_ecstore::{bucket, error, resolve_object_store_handle, store, store_api};
|
||||
pub(super) use rustfs_ecstore::{bucket, error, resolve_object_store_handle, store};
|
||||
|
||||
pub(super) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader};
|
||||
}
|
||||
}
|
||||
use self::ecstore::{
|
||||
bucket::{metadata::BucketMetadata, metadata_sys},
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
pub(crate) mod ecstore {
|
||||
pub(crate) use rustfs_ecstore::{error, resolve_object_store_handle, set_disk, store, store_api};
|
||||
pub(crate) use rustfs_ecstore::{error, resolve_object_store_handle, set_disk, store};
|
||||
|
||||
pub(crate) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{GetObjectReader, ObjectInfo, ObjectOptions};
|
||||
}
|
||||
}
|
||||
|
||||
use ecstore::store_api::{
|
||||
|
||||
@@ -16,8 +16,12 @@ use http::HeaderMap;
|
||||
pub(crate) mod ecstore {
|
||||
pub(crate) use rustfs_ecstore::{
|
||||
bucket, cache_value, config, data_usage, disk, error, global, pools, resolve_object_store_handle, set_disk, store,
|
||||
store_api, store_utils,
|
||||
store_utils,
|
||||
};
|
||||
|
||||
pub(crate) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader};
|
||||
}
|
||||
}
|
||||
pub(crate) use self::ecstore::{
|
||||
bucket::{
|
||||
@@ -49,11 +53,11 @@ pub(crate) use self::ecstore::{
|
||||
store::ECStore,
|
||||
store_api::{
|
||||
GetObjectReader as EcstoreGetObjectReader, ObjectInfo as EcstoreObjectInfo, ObjectOptions as EcstoreObjectOptions,
|
||||
ObjectToDelete as EcstoreObjectToDelete, PutObjReader as EcstorePutObjReader,
|
||||
PutObjReader as EcstorePutObjReader,
|
||||
},
|
||||
store_utils::is_reserved_or_invalid_bucket,
|
||||
};
|
||||
use rustfs_storage_api::{HTTPRangeSpec, ObjectIO};
|
||||
use rustfs_storage_api::{HTTPRangeSpec, ObjectIO, ObjectToDelete};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -65,7 +69,7 @@ pub(crate) use self::ecstore::{
|
||||
pub type ScannerGetObjectReader = EcstoreGetObjectReader;
|
||||
pub type ScannerObjectInfo = EcstoreObjectInfo;
|
||||
pub type ScannerObjectOptions = EcstoreObjectOptions;
|
||||
pub type ScannerObjectToDelete = EcstoreObjectToDelete;
|
||||
pub type ScannerObjectToDelete = ObjectToDelete;
|
||||
pub type ScannerPutObjReader = EcstorePutObjReader;
|
||||
|
||||
pub(crate) fn resolve_scanner_object_store_handle() -> Option<Arc<ECStore>> {
|
||||
|
||||
@@ -29,6 +29,7 @@ doctest = false
|
||||
|
||||
[dependencies]
|
||||
async-trait.workspace = true
|
||||
rustfs-filemeta.workspace = true
|
||||
serde.workspace = true
|
||||
time.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
@@ -24,6 +24,7 @@ pub use admin::{DiskSetSelector, StorageAdminApi};
|
||||
pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};
|
||||
pub use error::{StorageErrorCode, StorageResult};
|
||||
pub use multipart::{CompletePart, ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};
|
||||
pub use object::{DeletedObject, ObjectToDelete};
|
||||
pub use object::{HTTPPreconditions, HTTPRangeError, HTTPRangeSpec, ObjectLockRetentionOptions};
|
||||
pub use object::{HealOperations, MultipartOperations, NamespaceLocking, ObjectIO, ObjectOperations};
|
||||
pub use object::{ListObjectVersionsInfo, ListObjectsInfo, ListObjectsV2Info, ListOperations, ObjectInfoOrErr};
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustfs_filemeta::{
|
||||
ReplicationState, ReplicationStatusType, VersionPurgeStatusType, replication_statuses_map, version_purge_statuses_map,
|
||||
};
|
||||
use time::OffsetDateTime;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -155,6 +159,57 @@ pub enum WalkVersionsSortOrder {
|
||||
Descending,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ObjectToDelete {
|
||||
pub object_name: String,
|
||||
pub version_id: Option<Uuid>,
|
||||
pub delete_marker_replication_status: Option<String>,
|
||||
pub version_purge_status: Option<VersionPurgeStatusType>,
|
||||
pub version_purge_statuses: Option<String>,
|
||||
pub replicate_decision_str: Option<String>,
|
||||
}
|
||||
|
||||
impl ObjectToDelete {
|
||||
pub fn replication_state(&self) -> ReplicationState {
|
||||
ReplicationState {
|
||||
replication_status_internal: self.delete_marker_replication_status.clone(),
|
||||
version_purge_status_internal: self.version_purge_statuses.clone(),
|
||||
replicate_decision_str: self.replicate_decision_str.clone().unwrap_or_default(),
|
||||
targets: replication_statuses_map(self.delete_marker_replication_status.as_deref().unwrap_or_default()),
|
||||
purge_targets: version_purge_statuses_map(self.version_purge_statuses.as_deref().unwrap_or_default()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DeletedObject {
|
||||
pub delete_marker: bool,
|
||||
pub delete_marker_version_id: Option<Uuid>,
|
||||
pub object_name: String,
|
||||
pub version_id: Option<Uuid>,
|
||||
pub delete_marker_mtime: Option<OffsetDateTime>,
|
||||
pub replication_state: Option<ReplicationState>,
|
||||
pub found: bool,
|
||||
pub force_delete: bool,
|
||||
}
|
||||
|
||||
impl DeletedObject {
|
||||
pub fn version_purge_status(&self) -> VersionPurgeStatusType {
|
||||
self.replication_state
|
||||
.as_ref()
|
||||
.map(|v| v.composite_version_purge_status())
|
||||
.unwrap_or(VersionPurgeStatusType::Empty)
|
||||
}
|
||||
|
||||
pub fn delete_marker_replication_status(&self) -> ReplicationStatusType {
|
||||
self.replication_state
|
||||
.as_ref()
|
||||
.map(|v| v.composite_replication_status())
|
||||
.unwrap_or(ReplicationStatusType::Empty)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WalkOptions<Filter> {
|
||||
pub filter: Option<Filter>,
|
||||
@@ -714,6 +769,34 @@ mod tests {
|
||||
assert!(!opts.include_free_versions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_to_delete_builds_replication_state() {
|
||||
let object = ObjectToDelete {
|
||||
object_name: "photo.jpg".to_owned(),
|
||||
delete_marker_replication_status: Some("PENDING".to_owned()),
|
||||
version_purge_statuses: Some("arn:minio:replication:::target=PENDING".to_owned()),
|
||||
replicate_decision_str: Some("arn:minio:replication:::target=PENDING".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let state = object.replication_state();
|
||||
|
||||
assert_eq!(state.replication_status_internal.as_deref(), Some("PENDING"));
|
||||
assert_eq!(
|
||||
state.version_purge_status_internal.as_deref(),
|
||||
Some("arn:minio:replication:::target=PENDING")
|
||||
);
|
||||
assert_eq!(state.replicate_decision_str, "arn:minio:replication:::target=PENDING");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deleted_object_status_helpers_default_to_empty() {
|
||||
let object = DeletedObject::default();
|
||||
|
||||
assert_eq!(object.version_purge_status(), VersionPurgeStatusType::Empty);
|
||||
assert_eq!(object.delete_marker_replication_status(), ReplicationStatusType::Empty);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TestListBackend;
|
||||
|
||||
|
||||
@@ -5,18 +5,18 @@ 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-compat-reexport-prune`
|
||||
- Baseline: `origin/main` after `rustfs/rustfs#3578`
|
||||
(`f3fcdd4ba26181e3fe5d3afb6d6f5510bb9ad186`).
|
||||
- Branch: `overtrue/arch-delete-object-contracts`
|
||||
- Baseline: stacked on `rustfs/rustfs#3579` head
|
||||
(`903aff047d2faffaec907637d64440c84053f62e`).
|
||||
- PR type for this branch: `consumer-migration`
|
||||
- Runtime behavior changes: no migration behavior change expected.
|
||||
- Rust code changes: prune unused ECStore compatibility re-export allowances
|
||||
from production and fuzz compatibility boundaries, keep target-specific test
|
||||
harness exceptions explicit, and gate test-only RustFS storage compatibility
|
||||
re-exports with `cfg(test)`.
|
||||
- CI/script changes: add a migration guard rejecting production
|
||||
`storage_compat.rs` unused-import allows.
|
||||
- Docs changes: record the compatibility re-export pruning slice.
|
||||
- Rust code changes: move delete-object DTO contracts from ECStore store_api to
|
||||
rustfs-storage-api, keep ECStore old-path type aliases, and migrate RustFS,
|
||||
scanner, and ECStore internal consumers to the storage-api contracts.
|
||||
- CI/script changes: add a migration guard rejecting reintroduced ECStore
|
||||
delete DTO definitions, public re-exports, or internal old-path consumers.
|
||||
- Docs changes: record the delete-object contract move and consumer cleanup
|
||||
slices.
|
||||
|
||||
## Phase 0 Tasks
|
||||
|
||||
@@ -987,6 +987,68 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
layer guards, formatting check, diff hygiene, risk scan, full pre-commit,
|
||||
and required three-expert review passed.
|
||||
|
||||
- [x] `API-036` Move delete-object DTO contracts.
|
||||
- Current branch: `overtrue/arch-delete-object-contracts`.
|
||||
- Current slice: move `ObjectToDelete` and `DeletedObject` from ECStore
|
||||
`store_api` into `rustfs-storage-api`, keep old ECStore paths as type
|
||||
aliases for compatibility, migrate RustFS/scanner aliases to the
|
||||
storage-api contracts, and guard against reintroducing ECStore-owned delete
|
||||
DTO definitions.
|
||||
- Acceptance: storage-api exports delete-object DTO contracts, ECStore keeps
|
||||
compatibility type aliases without owning the definitions, external
|
||||
RustFS/scanner aliases consume storage-api directly, and migration rules
|
||||
reject restoring ECStore definitions or public re-exports.
|
||||
- Must preserve: delete-object field names and types, replication-state helper
|
||||
semantics, ECStore object/delete operation associated types, scanner delete
|
||||
selection behavior, RustFS object delete behavior, and old ECStore import
|
||||
compatibility.
|
||||
- Risk defense: this is a pure DTO ownership move; it does not change
|
||||
deletion control flow, replication decisions, lifecycle expiry behavior, or
|
||||
object metadata persistence.
|
||||
- Verification: focused compile checks, storage-api tests, migration and layer
|
||||
guards, formatting check, diff hygiene, risk scan, full pre-commit, and
|
||||
required three-expert review passed.
|
||||
|
||||
- [x] `API-037` Clean delete-object DTO consumers.
|
||||
- Current branch: `overtrue/arch-delete-object-contracts`.
|
||||
- Current slice: migrate ECStore internal delete-object DTO consumers from
|
||||
old `crate::store_api` imports to `rustfs-storage-api` contracts while
|
||||
keeping public ECStore type aliases for downstream compatibility.
|
||||
- Acceptance: ECStore object, set, lifecycle, and replication internals use
|
||||
storage-api delete DTO contracts directly; public old-path type aliases
|
||||
remain available; migration rules reject reintroducing ECStore internal
|
||||
old-path delete DTO consumers.
|
||||
- Must preserve: object delete result shape, batch delete error alignment,
|
||||
lifecycle replication scheduling, MRF delete replay, replication retry
|
||||
decisions, and old ECStore public import compatibility.
|
||||
- Risk defense: this is a consumer import cleanup over identical type
|
||||
definitions; it does not change delete control flow, replication decisions,
|
||||
lifecycle expiry behavior, or object metadata persistence.
|
||||
- Verification: focused ECStore/RustFS/scanner compile checks, migration and
|
||||
layer guards, formatting check, diff hygiene, risk scan, full pre-commit,
|
||||
and required three-expert review passed.
|
||||
|
||||
- [x] `API-038` Narrow remaining `store_api` compatibility re-export surfaces.
|
||||
- Current branch: `overtrue/arch-delete-object-contracts`.
|
||||
- Current slice: replace whole-module `rustfs_ecstore::store_api`
|
||||
compatibility re-exports in RustFS storage, scanner, heal, Swift,
|
||||
S3 Select, IAM, and notify boundaries with explicit contract type
|
||||
re-exports, and add a migration rule rejecting broad `store_api`
|
||||
compatibility re-exports.
|
||||
- Acceptance: storage compatibility boundaries expose only the concrete
|
||||
`store_api` contracts their consumers use; downstream local aliases keep
|
||||
the same names; migration rules reject reintroducing broad `store_api`
|
||||
passthroughs in production compatibility boundaries.
|
||||
- Must preserve: object info/options reader aliases, storage/list/multipart
|
||||
operation trait bindings, scanner/heal/Swift/S3 Select/IAM/notify behavior,
|
||||
and all ECStore-owned concrete type ownership.
|
||||
- Risk defense: this is compatibility import surface cleanup only; it does
|
||||
not move definitions, alter storage/runtime control flow, change object
|
||||
metadata conversion, or mutate reader behavior.
|
||||
- Verification: focused multi-crate compile, migration guard, formatting
|
||||
check, diff hygiene, risk scan, full pre-commit, and required three-expert
|
||||
review passed.
|
||||
|
||||
## Phase 8 Background Controller Tasks
|
||||
|
||||
- [x] `BGC-001` Inventory background services.
|
||||
@@ -1263,14 +1325,53 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
||||
|
||||
| Expert | Status | Notes |
|
||||
|---|---|---|
|
||||
| Quality/architecture | passed | Production compatibility boundaries no longer hide unused ECStore re-exports behind broad unused-import allows; target-specific test exceptions remain scoped. |
|
||||
| Migration preservation | passed | ECStore remains the owner of backing types and behavior; this slice only changes compatibility-boundary hygiene and guard coverage. |
|
||||
| Testing/verification | passed | Focused compile checks, fuzz manifest compile, guards, formatting, diff hygiene, risk scan, and full `make pre-commit` passed. |
|
||||
| Quality/architecture | passed | Delete-object DTO ownership lives in storage-api; ECStore internal consumers use storage-api directly while public aliases remain, and store_api compatibility boundaries now expose explicit contract types only. |
|
||||
| Migration preservation | passed | Field shape, helper semantics, delete behavior, replication scheduling, MRF delete replay, object info/options aliases, reader aliases, and old ECStore public import compatibility are preserved. |
|
||||
| Testing/verification | passed | Multi-crate compile, guards, formatting, diff hygiene, risk scan, and full `make pre-commit` passed. |
|
||||
|
||||
## Verification Notes
|
||||
|
||||
Passed before push:
|
||||
|
||||
- API-038 current slice:
|
||||
- `cargo check --tests -p rustfs -p rustfs-scanner -p rustfs-heal -p rustfs-protocols -p rustfs-s3select-api -p rustfs-iam -p rustfs-notify`:
|
||||
passed.
|
||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||
- `cargo fmt --all --check`: passed.
|
||||
- `git diff --check`: passed.
|
||||
- Rust risk scan: passed; no new unwrap/expect, numeric casts, string error
|
||||
public APIs, boxed public errors, production println/eprintln, or relaxed
|
||||
ordering introduced in changed Rust files.
|
||||
- `make pre-commit`: passed.
|
||||
|
||||
- API-037 current slice:
|
||||
- `cargo check --tests -p rustfs-ecstore -p rustfs -p rustfs-scanner`:
|
||||
passed.
|
||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||
- `cargo fmt --all --check`: passed.
|
||||
- `git diff --check`: passed.
|
||||
- Rust risk scan: passed; no new unwrap/expect, numeric casts, string error
|
||||
public APIs, boxed public errors, production println/eprintln, or relaxed
|
||||
ordering introduced in changed Rust files.
|
||||
- `make pre-commit`: passed.
|
||||
|
||||
- API-036 current slice:
|
||||
- `cargo test -p rustfs-storage-api`: passed.
|
||||
- `cargo check --tests -p rustfs-storage-api -p rustfs-ecstore -p rustfs-scanner -p rustfs`:
|
||||
passed.
|
||||
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||
- `cargo fmt --all --check`: passed.
|
||||
- `git diff --check`: passed.
|
||||
- Rust risk scan: passed; no new unwrap/expect, numeric casts, string error
|
||||
public APIs, boxed public errors, production println/eprintln, or relaxed
|
||||
ordering introduced in changed Rust files.
|
||||
- `make pre-commit`: passed.
|
||||
|
||||
API-035 prior slice:
|
||||
|
||||
- `cargo check --tests -p rustfs-scanner -p rustfs-heal -p rustfs-iam`:
|
||||
passed.
|
||||
- `cargo check --tests -p rustfs-protocols --features swift`: passed.
|
||||
|
||||
@@ -28,11 +28,11 @@ pub(crate) mod storage_compat;
|
||||
pub mod timeout_wrapper;
|
||||
pub mod tonic_service;
|
||||
|
||||
pub(crate) type StorageDeletedObject = crate::storage::storage_compat::ecstore::store_api::DeletedObject;
|
||||
pub(crate) type StorageDeletedObject = rustfs_storage_api::DeletedObject;
|
||||
pub(crate) type StorageGetObjectReader = crate::storage::storage_compat::ecstore::store_api::GetObjectReader;
|
||||
pub(crate) type StorageObjectInfo = crate::storage::storage_compat::ecstore::store_api::ObjectInfo;
|
||||
pub(crate) type StorageObjectOptions = crate::storage::storage_compat::ecstore::store_api::ObjectOptions;
|
||||
pub(crate) type StorageObjectToDelete = crate::storage::storage_compat::ecstore::store_api::ObjectToDelete;
|
||||
pub(crate) type StorageObjectToDelete = rustfs_storage_api::ObjectToDelete;
|
||||
pub(crate) type StoragePutObjReader = crate::storage::storage_compat::ecstore::store_api::PutObjReader;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -15,9 +15,13 @@
|
||||
pub(crate) mod ecstore {
|
||||
pub(crate) use rustfs_ecstore::{
|
||||
admin_server_info, bucket, client, disk, error, get_global_lock_client, global, metrics_realtime,
|
||||
resolve_object_store_handle, rio, rpc, set_disk, store, store_api,
|
||||
resolve_object_store_handle, rio, rpc, set_disk, store,
|
||||
};
|
||||
|
||||
pub(crate) mod store_api {
|
||||
pub(crate) use rustfs_ecstore::store_api::{GetObjectReader, ObjectInfo, ObjectOptions, PutObjReader};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) use rustfs_ecstore::config;
|
||||
}
|
||||
|
||||
@@ -10481,9 +10481,7 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
backend.seed_object(bucket, &new_metadata, b"{}".to_vec()).await;
|
||||
backend
|
||||
.fail_put_attempt(rustfs_ecstore::disk::RUSTFS_META_BUCKET, &commit_path, 2)
|
||||
.await;
|
||||
backend.fail_put_attempt(RUSTFS_META_BUCKET, &commit_path, 2).await;
|
||||
|
||||
store
|
||||
.commit_table(TableCommitRequest {
|
||||
|
||||
@@ -57,11 +57,14 @@ STORE_API_OBJECT_HELPER_REEXPORTS_FILE="${TMP_DIR}/store_api_object_helper_reexp
|
||||
STORE_API_RANGE_HELPER_REEXPORTS_FILE="${TMP_DIR}/store_api_range_helper_reexports.txt"
|
||||
STORE_API_LIST_HELPER_REEXPORTS_FILE="${TMP_DIR}/store_api_list_helper_reexports.txt"
|
||||
STORE_API_LIST_RESPONSE_REEXPORTS_FILE="${TMP_DIR}/store_api_list_response_reexports.txt"
|
||||
STORE_API_DELETE_DTO_REEXPORTS_FILE="${TMP_DIR}/store_api_delete_dto_reexports.txt"
|
||||
STORE_API_DELETE_DTO_INTERNAL_HITS_FILE="${TMP_DIR}/store_api_delete_dto_internal_hits.txt"
|
||||
STORE_API_EXTERNAL_LIST_CONSUMER_HITS_FILE="${TMP_DIR}/store_api_external_list_consumer_hits.txt"
|
||||
STORE_API_EXTERNAL_OPERATION_CONSUMER_HITS_FILE="${TMP_DIR}/store_api_external_operation_consumer_hits.txt"
|
||||
STORE_API_OBJECT_OPERATION_LOCAL_METHOD_HITS_FILE="${TMP_DIR}/store_api_object_operation_local_method_hits.txt"
|
||||
DIRECT_ECSTORE_IMPORT_HITS_FILE="${TMP_DIR}/direct_ecstore_import_hits.txt"
|
||||
PRODUCTION_UNUSED_COMPAT_ALLOW_HITS_FILE="${TMP_DIR}/production_unused_compat_allow_hits.txt"
|
||||
BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE="${TMP_DIR}/broad_store_api_compat_reexport_hits.txt"
|
||||
|
||||
awk '
|
||||
/^## PR Types$/ {
|
||||
@@ -202,6 +205,10 @@ require_source_line \
|
||||
"crates/storage-api/src/lib.rs" \
|
||||
"pub use object::{HTTPPreconditions, HTTPRangeError, HTTPRangeSpec, ObjectLockRetentionOptions};" \
|
||||
"storage-api public object helper contract re-export"
|
||||
require_source_line \
|
||||
"crates/storage-api/src/lib.rs" \
|
||||
"pub use object::{DeletedObject, ObjectToDelete};" \
|
||||
"storage-api public delete object contract re-export"
|
||||
require_source_line \
|
||||
"crates/storage-api/src/lib.rs" \
|
||||
"pub use object::{ListObjectVersionsInfo, ListObjectsInfo, ListObjectsV2Info, ListOperations, ObjectInfoOrErr};" \
|
||||
@@ -302,6 +309,26 @@ if [[ -s "$STORE_API_LIST_RESPONSE_REEXPORTS_FILE" ]]; then
|
||||
report_failure "old ecstore store_api list response path reintroduced: $(paste -sd '; ' "$STORE_API_LIST_RESPONSE_REEXPORTS_FILE")"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ROOT_DIR"
|
||||
rg -n --no-heading 'pub(?:\(crate\))? use rustfs_storage_api(?:::\{[^}]*\b(?:DeletedObject|ObjectToDelete)\b|::(?:DeletedObject|ObjectToDelete)\b)|pub struct (?:DeletedObject|ObjectToDelete)\b' \
|
||||
crates/ecstore/src/store_api.rs crates/ecstore/src/store_api/types.rs || true
|
||||
) >"$STORE_API_DELETE_DTO_REEXPORTS_FILE"
|
||||
|
||||
if [[ -s "$STORE_API_DELETE_DTO_REEXPORTS_FILE" ]]; then
|
||||
report_failure "old ecstore store_api delete DTO path reintroduced: $(paste -sd '; ' "$STORE_API_DELETE_DTO_REEXPORTS_FILE")"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ROOT_DIR"
|
||||
rg -n --no-heading 'crate::store_api::(?:DeletedObject|ObjectToDelete)|store_api::\{[^}]*\b(?:DeletedObject|ObjectToDelete)\b' \
|
||||
crates/ecstore/src --glob '*.rs' --glob '!store_api/types.rs' || true
|
||||
) >"$STORE_API_DELETE_DTO_INTERNAL_HITS_FILE"
|
||||
|
||||
if [[ -s "$STORE_API_DELETE_DTO_INTERNAL_HITS_FILE" ]]; then
|
||||
report_failure "ecstore internal delete DTO old store_api path reintroduced: $(paste -sd '; ' "$STORE_API_DELETE_DTO_INTERNAL_HITS_FILE")"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ROOT_DIR"
|
||||
rg -n --no-heading 'rustfs_ecstore::store_api(?:::\{[^}]*\b(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b|::(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b)' \
|
||||
@@ -348,6 +375,19 @@ if [[ -s "$PRODUCTION_UNUSED_COMPAT_ALLOW_HITS_FILE" ]]; then
|
||||
report_failure "production storage compatibility boundaries must not hide unused ECStore re-exports: $(paste -sd '; ' "$PRODUCTION_UNUSED_COMPAT_ALLOW_HITS_FILE")"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ROOT_DIR"
|
||||
rg -n --no-heading '(?:use|pub(?:\([^)]*\))? use) rustfs_ecstore::\{[^}]*\bstore_api\b[^}]*\}|(?:use|pub(?:\([^)]*\))? use) rustfs_ecstore::store_api\s*(?:;|as\b)' \
|
||||
rustfs/src crates/*/src fuzz/fuzz_targets \
|
||||
--glob '*storage_compat.rs' \
|
||||
--glob '!crates/ecstore/**' \
|
||||
--glob '!crates/e2e_test/**' || true
|
||||
) >"$BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE"
|
||||
|
||||
if [[ -s "$BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE" ]]; then
|
||||
report_failure "storage compatibility boundaries must expose explicit store_api contracts only: $(paste -sd '; ' "$BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE")"
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$ROOT_DIR"
|
||||
rg -n --no-heading 'async fn (get_object_reader|put_object|get_object_info|verify_object_integrity|copy_object|delete_object_version|delete_object|delete_objects|put_object_metadata|get_object_tags|put_object_tags|delete_object_tags|add_partial|transition_object|restore_transitioned_object|list_multipart_uploads|new_multipart_upload|copy_object_part|put_object_part|get_multipart_info|list_object_parts|abort_multipart_upload|complete_multipart_upload|heal_format|heal_bucket|heal_object|get_pool_and_set|check_abandoned_parts|new_ns_lock)\b' \
|
||||
|
||||
Reference in New Issue
Block a user