refactor(replication): own delete DTO contracts (#4253)

This commit is contained in:
Zhengchao An
2026-07-04 04:00:27 +08:00
committed by GitHub
parent 8a0617865b
commit 125c228832
14 changed files with 159 additions and 74 deletions
@@ -20,7 +20,9 @@ use super::replication_filemeta_boundary::{
};
use super::replication_object_config::{ReplicationConfig, check_replicate_delete};
use super::replication_queue_boundary::DeletedObjectReplicationInfo;
use super::replication_storage_boundary::{DeletedObject, ObjectInfo, ObjectOptions, ObjectToDelete};
use super::replication_storage_boundary::{
DeletedObject, ObjectInfo, ObjectOptions, ObjectToDelete, deleted_object_for_replication,
};
pub(crate) type ReplicationLifecycleConfig = ReplicationConfig;
@@ -64,7 +66,7 @@ impl ReplicationLifecycleBridge {
pub(crate) async fn schedule_delete(bucket: String, delete_object: DeletedObject) {
super::replication_pool::schedule_replication_delete(DeletedObjectReplicationInfo {
delete_object,
delete_object: deleted_object_for_replication(delete_object),
bucket,
event_type: REPLICATE_INCOMING_DELETE.to_string(),
..Default::default()
@@ -19,7 +19,9 @@ use super::replication_object_config::{check_replicate_delete, get_must_replicat
use super::replication_object_decision_boundary::MustReplicateOptions;
use super::replication_pool::{schedule_replication, schedule_replication_delete};
use super::replication_queue_boundary::DeletedObjectReplicationInfo;
use super::replication_storage_boundary::{ObjectInfo, ObjectOptions, ObjectToDelete, ReplicationStorage};
use super::replication_storage_boundary::{
DeletedObject, ObjectInfo, ObjectOptions, ObjectToDelete, ReplicationStorage, deleted_object_for_replication,
};
pub struct ReplicationObjectBridge;
@@ -60,6 +62,16 @@ impl ReplicationObjectBridge {
pub async fn schedule_delete(delete_object: DeletedObjectReplicationInfo) {
schedule_replication_delete(delete_object).await;
}
pub async fn schedule_storage_delete(delete_object: DeletedObject, bucket: String, event_type: String) {
Self::schedule_delete(DeletedObjectReplicationInfo {
delete_object: deleted_object_for_replication(delete_object),
bucket,
event_type,
..Default::default()
})
.await;
}
}
#[cfg(test)]
@@ -30,7 +30,7 @@ use super::replication_object_decision_boundary::{
MustReplicateOptions, ReplicationDeleteSource, ReplicationResyncTargetObject, delete_replication_missing_source_decision,
delete_replication_object_opts, resync_target_for_object,
};
use super::replication_storage_boundary::{ObjectInfo, ObjectOptions, ObjectToDelete};
use super::replication_storage_boundary::{ObjectInfo, ObjectOptions, ObjectToDelete, object_to_delete_for_replication};
use super::replication_target_boundary::{BucketTargets, ReplicationTargetStore};
use super::replication_versioning_boundary::ReplicationVersioningStore;
use super::runtime_boundary as runtime_sources;
@@ -194,8 +194,9 @@ pub(crate) async fn check_replicate_delete(
return ReplicateDecision::default();
}
let replication_delete = object_to_delete_for_replication(dobj);
let opts = delete_replication_object_opts(
dobj,
&replication_delete,
&ReplicationDeleteSource {
user_defined: oi.user_defined.as_ref(),
user_tags: oi.user_tags.as_str(),
@@ -38,7 +38,9 @@ use super::replication_resyncer::{
ReplicationResyncer, get_heal_replicate_object_info, replicate_delete, replicate_object, save_resync_status,
};
use super::replication_state::ReplicationStats;
use super::replication_storage_boundary::{DeletedObject, ObjectInfo, ObjectOptions, ReplicationObjectIO, ReplicationStorage};
use super::replication_storage_boundary::{
ObjectInfo, ObjectOptions, ReplicationDeletedObject, ReplicationObjectIO, ReplicationStorage,
};
use super::replication_target_boundary::ReplicationTargetStore;
use super::runtime_boundary as runtime_sources;
use lazy_static::lazy_static;
@@ -616,7 +618,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: DeletedObject {
delete_object: ReplicationDeletedObject {
object_name: entry.object.clone(),
version_id: entry.version_id,
delete_marker_version_id: entry.delete_marker_version_id,
@@ -42,8 +42,8 @@ use super::replication_resync_boundary::{
#[cfg(test)]
use super::replication_resync_boundary::{RESYNC_META_FORMAT, RESYNC_META_VERSION, WIRE_ZERO_TIME_UNIX, decode_resync_file};
use super::replication_storage_boundary::{
AdvancedGetOptions, DeletedObject, EcstoreObjectOperations, HTTPRangeSpec, ObjectInfo, ObjectOptions, ObjectToDelete,
ReplicationObjectIO, ReplicationStorage, StatObjectOptions, WalkOptions,
AdvancedGetOptions, EcstoreObjectOperations, HTTPRangeSpec, ObjectInfo, ObjectOptions, ObjectToDelete,
ReplicationDeletedObject, ReplicationObjectIO, ReplicationStorage, StatObjectOptions, WalkOptions,
};
use super::replication_target_boundary::{
PutObjectOptions, PutObjectPartOptions, ReplicationTargetStore, TargetClient, replication_action_for_target_head,
@@ -671,7 +671,7 @@ impl ReplicationResyncer {
};
let doi = DeletedObjectReplicationInfo {
delete_object: DeletedObject {
delete_object: ReplicationDeletedObject {
object_name: roi.name.clone(),
delete_marker_version_id: dm_version_id,
version_id,
@@ -3131,7 +3131,7 @@ mod tests {
#[test]
fn test_is_version_delete_replication_for_delete_marker_version_purge() {
let dobj = DeletedObject {
let dobj = ReplicationDeletedObject {
delete_marker: false,
delete_marker_version_id: Some(Uuid::new_v4()),
..Default::default()
@@ -3145,7 +3145,7 @@ mod tests {
#[test]
fn test_is_version_delete_replication_for_delete_marker_creation() {
let dobj = DeletedObject {
let dobj = ReplicationDeletedObject {
delete_marker: true,
delete_marker_version_id: Some(Uuid::new_v4()),
..Default::default()
@@ -3159,7 +3159,7 @@ mod tests {
#[test]
fn test_should_retry_delete_marker_purge_for_version_purge() {
let dobj = DeletedObject {
let dobj = ReplicationDeletedObject {
delete_marker: false,
delete_marker_version_id: Some(Uuid::new_v4()),
..Default::default()
@@ -3173,7 +3173,7 @@ mod tests {
#[test]
fn test_should_retry_delete_marker_purge_for_delete_marker_creation() {
let dobj = DeletedObject {
let dobj = ReplicationDeletedObject {
delete_marker: true,
delete_marker_version_id: Some(Uuid::new_v4()),
..Default::default()
@@ -27,6 +27,7 @@ pub(crate) use crate::storage_api_contracts::object::{
DeletedObject, EcstoreObjectOperations, ObjectIO, ObjectOperations, ObjectToDelete,
};
pub(crate) use crate::storage_api_contracts::range::HTTPRangeSpec;
pub(crate) use rustfs_replication::{DeletedObject as ReplicationDeletedObject, ObjectToDelete as ReplicationObjectToDelete};
type ListObjectsV2Info = StorageListObjectsV2Info<ObjectInfo>;
type ListObjectVersionsInfo = StorageListObjectVersionsInfo<ObjectInfo>;
@@ -93,6 +94,30 @@ pub trait ReplicationStorage:
{
}
pub(crate) fn deleted_object_for_replication(delete_object: DeletedObject) -> ReplicationDeletedObject {
ReplicationDeletedObject {
delete_marker: delete_object.delete_marker,
delete_marker_version_id: delete_object.delete_marker_version_id,
object_name: delete_object.object_name,
version_id: delete_object.version_id,
delete_marker_mtime: delete_object.delete_marker_mtime,
replication_state: delete_object.replication_state,
found: delete_object.found,
force_delete: delete_object.force_delete,
}
}
pub(crate) fn object_to_delete_for_replication(object: &ObjectToDelete) -> ReplicationObjectToDelete {
ReplicationObjectToDelete {
object_name: object.object_name.clone(),
version_id: object.version_id,
delete_marker_replication_status: object.delete_marker_replication_status.clone(),
version_purge_status: object.version_purge_status.clone(),
version_purge_statuses: object.version_purge_statuses.clone(),
replicate_decision_str: object.replicate_decision_str.clone(),
}
}
impl<T> ReplicationStorage for T where
T: ObjectIO<
Error = Error,
-1
View File
@@ -30,7 +30,6 @@ byteorder.workspace = true
rmp.workspace = true
rmp-serde.workspace = true
rustfs-filemeta.workspace = true
rustfs-storage-api.workspace = true
rustfs-utils = { workspace = true, features = ["http", "path", "string"] }
s3s.workspace = true
serde.workspace = true
+1
View File
@@ -82,4 +82,5 @@ pub use stats::{
FailedMetric, InQueueMetric, InQueueStats, LatencyStats, ProxyMetric, ProxyStatsCache, QueueCache, QueueNode, QueueStats,
SRMetricsSummary, XferStats,
};
pub use storage_api::{DeletedObject, ObjectToDelete};
pub use tagging::{ReplicationTagFilter, decode_tags_to_map};
+54 -1
View File
@@ -12,4 +12,57 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub(crate) use rustfs_storage_api::{DeletedObject, ObjectToDelete};
use crate::{ReplicationState, ReplicationStatusType, VersionPurgeStatusType};
use time::OffsetDateTime;
use uuid::Uuid;
#[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: crate::replication_statuses_map(self.delete_marker_replication_status.as_deref().unwrap_or_default()),
purge_targets: crate::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)
}
}