diff --git a/crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs b/crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs index e83a8a690..997f64ccc 100644 --- a/crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs +++ b/crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs @@ -14,8 +14,8 @@ pub(crate) use rustfs_replication::{MrfOpKind, MrfReplicateEntry}; pub(crate) use rustfs_replication::{ - REPLICATE_EXISTING, REPLICATE_EXISTING_DELETE, REPLICATE_HEAL, REPLICATE_HEAL_DELETE, REPLICATE_INCOMING_DELETE, - ReplicateDecision, ReplicateObjectInfo, ReplicateTargetDecision, ReplicatedInfos, ReplicatedTargetInfo, ReplicationAction, - ReplicationState, ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, ResyncDecision, VersionPurgeStatusType, + REPLICATE_EXISTING, REPLICATE_EXISTING_DELETE, REPLICATE_HEAL_DELETE, REPLICATE_INCOMING_DELETE, ReplicateDecision, + ReplicateObjectInfo, ReplicateTargetDecision, ReplicatedInfos, ReplicatedTargetInfo, ReplicationAction, ReplicationState, + ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, ResyncDecision, VersionPurgeStatusType, get_replication_state, parse_replicate_decision, replication_statuses_map, target_reset_header, version_purge_statuses_map, }; diff --git a/crates/ecstore/src/bucket/replication/replication_pool.rs b/crates/ecstore/src/bucket/replication/replication_pool.rs index edfef7e99..4fcd15f77 100644 --- a/crates/ecstore/src/bucket/replication/replication_pool.rs +++ b/crates/ecstore/src/bucket/replication/replication_pool.rs @@ -16,9 +16,9 @@ use super::datatypes::ResyncStatusType; use super::replication_config_store::ReplicationConfigStore; use super::replication_error_boundary::Error as EcstoreError; use super::replication_filemeta_boundary::{ - MrfOpKind, MrfReplicateEntry, REPLICATE_EXISTING, REPLICATE_HEAL, REPLICATE_HEAL_DELETE, ReplicateDecision, - ReplicateObjectInfo, ReplicatedTargetInfo, ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, - ResyncDecision, VersionPurgeStatusType, replication_statuses_map, version_purge_statuses_map, + MrfOpKind, MrfReplicateEntry, REPLICATE_HEAL_DELETE, ReplicateDecision, ReplicateObjectInfo, ReplicatedTargetInfo, + ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, ResyncDecision, replication_statuses_map, + version_purge_statuses_map, }; use super::replication_metadata_boundary::ReplicationMetadataStore; use super::replication_resyncer::{ @@ -32,10 +32,11 @@ use super::runtime_boundary as runtime_sources; use super::{BucketReplicationResyncStatus, ResyncOpts, TargetReplicationResyncStatus}; use lazy_static::lazy_static; use rustfs_replication::{ - DeletedObjectReplicationInfo, LARGE_WORKER_COUNT, ReplicationHealQueueResult, ReplicationOperation, ReplicationPoolOpts, - ReplicationPriority, ReplicationQueueAdmission, WORKER_MAX_LIMIT, initial_worker_counts, mrf_worker_size_to_count, - next_large_worker_count, next_mrf_worker_count, next_regular_worker_count, resized_worker_counts, should_grow_large_workers, - should_queue_large_object, + DeletedObjectReplicationInfo, LARGE_WORKER_COUNT, ReplicationHealQueueAction, ReplicationHealQueueResult, + ReplicationHealResyncDeletes, ReplicationOperation, ReplicationPoolOpts, ReplicationPriority, ReplicationQueueAdmission, + WORKER_MAX_LIMIT, initial_worker_counts, mrf_worker_size_to_count, next_large_worker_count, next_mrf_worker_count, + next_regular_worker_count, replication_heal_queue_action, resized_worker_counts, should_auto_resume_resync, + should_grow_large_workers, should_queue_large_object, }; use rustfs_utils::http::{SUFFIX_REPLICATION_TIMESTAMP, get_str}; use std::sync::Arc; @@ -63,10 +64,6 @@ const EVENT_REPLICATION_RESYNC_RECOVERED: &str = "replication_resync_recovered"; const EVENT_REPLICATION_CONFIG_LOOKUP_SKIPPED: &str = "replication_config_lookup_skipped"; const EVENT_REPLICATION_MRF_QUEUE_OVERFLOW: &str = "replication_mrf_queue_overflow"; -fn should_auto_resume_resync(status: ResyncStatusType) -> bool { - matches!(status, ResyncStatusType::ResyncPending | ResyncStatusType::ResyncStarted) -} - /// Main replication pool structure #[derive(Debug)] pub struct ReplicationPool { @@ -1383,140 +1380,52 @@ pub(crate) async fn queue_replication_heal_internal( roi = get_heal_replicate_object_info(&oi, &rcfg).await; roi.retry_count = retry_count; - if !roi.dsc.replicate_any() { - return ReplicationHealQueueResult { + match replication_heal_queue_action(&mut roi) { + ReplicationHealQueueAction::Skip => ReplicationHealQueueResult { object_info: roi, admission: ReplicationQueueAdmission::Skipped, - }; - } - - // early return if replication already done, otherwise we need to determine if this - // version is an existing object that needs healing. - if roi.replication_status == ReplicationStatusType::Completed - && roi.version_purge_status.is_empty() - && !roi.existing_obj_resync.must_resync() - { - return ReplicationHealQueueResult { - object_info: roi, - admission: ReplicationQueueAdmission::Skipped, - }; - } - - if roi.delete_marker || !roi.version_purge_status.is_empty() { - let (version_id, dm_version_id) = if roi.version_purge_status.is_empty() { - (None, roi.version_id) - } else { - (roi.version_id, None) - }; - - let dv = DeletedObjectReplicationInfo { - delete_object: DeletedObject { - object_name: roi.name.clone(), - delete_marker_version_id: dm_version_id, - version_id, - replication_state: roi.replication_state.clone(), - delete_marker_mtime: roi.mod_time, - delete_marker: roi.delete_marker, - ..Default::default() - }, - bucket: roi.bucket.clone(), - op_type: ReplicationType::Heal, - event_type: REPLICATE_HEAL_DELETE.to_string(), - ..Default::default() - }; - - // heal delete marker replication failure or versioned delete replication failure - if roi.replication_status == ReplicationStatusType::Pending - || roi.replication_status == ReplicationStatusType::Failed - || roi.version_purge_status == VersionPurgeStatusType::Failed - || roi.version_purge_status == VersionPurgeStatusType::Pending - { - let admission = if let Some(pool) = runtime_sources::replication_pool() { - pool.queue_replica_delete_task(dv).await - } else { - ReplicationQueueAdmission::Missed - }; - return ReplicationHealQueueResult { - object_info: roi, - admission, - }; - } - - // if replication status is Complete on DeleteMarker and existing object resync required - let existing_obj_resync = roi.existing_obj_resync.clone(); - if existing_obj_resync.must_resync() - && (roi.replication_status == ReplicationStatusType::Completed || roi.replication_status.is_empty()) - { - let admission = queue_replicate_deletes_wrapper(dv, existing_obj_resync).await; - return ReplicationHealQueueResult { - object_info: roi, - admission, - }; - } - - return ReplicationHealQueueResult { - object_info: roi, - admission: ReplicationQueueAdmission::Skipped, - }; - } - - if roi.existing_obj_resync.must_resync() { - roi.op_type = ReplicationType::ExistingObject; - } - - match roi.replication_status { - ReplicationStatusType::Pending | ReplicationStatusType::Failed => { - roi.event_type = REPLICATE_HEAL.to_string(); + }, + ReplicationHealQueueAction::QueueObject => { let admission = if let Some(pool) = runtime_sources::replication_pool() { pool.queue_replica_task(roi.clone()).await } else { ReplicationQueueAdmission::Missed }; - return ReplicationHealQueueResult { + ReplicationHealQueueResult { object_info: roi, admission, - }; + } } - _ => {} - } - - if roi.existing_obj_resync.must_resync() { - roi.event_type = REPLICATE_EXISTING.to_string(); - let admission = if let Some(pool) = runtime_sources::replication_pool() { - pool.queue_replica_task(roi.clone()).await - } else { - ReplicationQueueAdmission::Missed - }; - return ReplicationHealQueueResult { - object_info: roi, - admission, - }; - } - - ReplicationHealQueueResult { - object_info: roi, - admission: ReplicationQueueAdmission::Skipped, - } -} - -/// Wrapper function for queueing replicate deletes with resync decision -async fn queue_replicate_deletes_wrapper( - doi: DeletedObjectReplicationInfo, - existing_obj_resync: ResyncDecision, -) -> ReplicationQueueAdmission { - let mut admission = ReplicationQueueAdmission::Skipped; - for (k, v) in existing_obj_resync.targets.iter() { - if v.replicate { - let mut dv = doi.clone(); - dv.reset_id = v.reset_id.clone(); - dv.target_arn = k.clone(); - let target_admission = if let Some(pool) = runtime_sources::replication_pool() { + ReplicationHealQueueAction::QueueDelete(dv) => { + let admission = if let Some(pool) = runtime_sources::replication_pool() { pool.queue_replica_delete_task(dv).await } else { ReplicationQueueAdmission::Missed }; - admission.merge(target_admission); + ReplicationHealQueueResult { + object_info: roi, + admission, + } } + ReplicationHealQueueAction::QueueResyncDeletes(batch) => { + let admission = queue_replicate_deletes(batch).await; + ReplicationHealQueueResult { + object_info: roi, + admission, + } + } + } +} + +async fn queue_replicate_deletes(batch: ReplicationHealResyncDeletes) -> ReplicationQueueAdmission { + let mut admission = ReplicationQueueAdmission::Skipped; + for dv in batch.target_delete_infos() { + let target_admission = if let Some(pool) = runtime_sources::replication_pool() { + pool.queue_replica_delete_task(dv).await + } else { + ReplicationQueueAdmission::Missed + }; + admission.merge(target_admission); } admission } @@ -1538,16 +1447,6 @@ mod tests { assert_eq!(admission, ReplicationQueueAdmission::Missed); } - #[test] - fn auto_resume_resync_only_for_inflight_states() { - assert!(should_auto_resume_resync(ResyncStatusType::ResyncPending)); - assert!(should_auto_resume_resync(ResyncStatusType::ResyncStarted)); - assert!(!should_auto_resume_resync(ResyncStatusType::NoResync)); - assert!(!should_auto_resume_resync(ResyncStatusType::ResyncCanceled)); - assert!(!should_auto_resume_resync(ResyncStatusType::ResyncCompleted)); - assert!(!should_auto_resume_resync(ResyncStatusType::ResyncFailed)); - } - // ── MrfReplicateEntry encode/decode roundtrips ──────────────────────────── #[test] diff --git a/crates/replication/src/lib.rs b/crates/replication/src/lib.rs index 51ec64dbe..1c1cfe10b 100644 --- a/crates/replication/src/lib.rs +++ b/crates/replication/src/lib.rs @@ -38,10 +38,14 @@ pub use operation::{ MustReplicateOptions, ReplicationDeleteSource, ReplicationResyncTargetObject, delete_replication_missing_source_decision, delete_replication_object_opts, heal_uses_delete_replication_path, is_ssec_encrypted, resync_target_for_object, }; -pub use queue::{ReplicationHealQueueResult, ReplicationOperation, ReplicationPriority, ReplicationQueueAdmission}; +pub use queue::{ + ReplicationHealQueueAction, ReplicationHealQueueResult, ReplicationHealResyncDeletes, ReplicationOperation, + ReplicationPriority, ReplicationQueueAdmission, replication_heal_queue_action, +}; pub use resync::{ BucketReplicationResyncStatus, Error, Result, ResyncOpts, ResyncStatusType, TargetReplicationResyncStatus, - decode_resync_file, encode_resync_file, is_version_id_mismatch, resync_state_accepts_update, should_count_head_proxy_failure, + decode_resync_file, encode_resync_file, is_version_id_mismatch, resync_state_accepts_update, should_auto_resume_resync, + should_count_head_proxy_failure, }; pub use rule::ReplicationRuleExt; pub use runtime::{ diff --git a/crates/replication/src/object.rs b/crates/replication/src/object.rs index 16bb5ff0e..e2f22ac26 100644 --- a/crates/replication/src/object.rs +++ b/crates/replication/src/object.rs @@ -140,10 +140,7 @@ fn tag_metadata_differs(source: &ReplicationSourceObject<'_>, target: &Replicati .and_then(|metadata| metadata.get(AMZ_OBJECT_TAGGING).map(String::as_str)) .unwrap_or_default(); let target_tags = ReplicationTagFilter::decode_tags_to_map(target_tagging); - let source_tag_count = match i32::try_from(source_tags.len()) { - Ok(count) => count, - Err(_) => i32::MAX, - }; + let source_tag_count = i32::try_from(source_tags.len()).unwrap_or(i32::MAX); (target.tag_count > 0 && source_tags != target_tags) || target.tag_count != source_tag_count } diff --git a/crates/replication/src/queue.rs b/crates/replication/src/queue.rs index 20567b51a..0a06e0e3f 100644 --- a/crates/replication/src/queue.rs +++ b/crates/replication/src/queue.rs @@ -14,7 +14,13 @@ use std::any::Any; -use crate::{DeletedObjectReplicationInfo, MrfReplicateEntry, ReplicateObjectInfo, ReplicationType, ReplicationWorkerOperation}; +use rustfs_storage_api::DeletedObject; + +use crate::{ + DeletedObjectReplicationInfo, MrfReplicateEntry, REPLICATE_EXISTING, REPLICATE_HEAL, REPLICATE_HEAL_DELETE, + ReplicateObjectInfo, ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, ResyncDecision, + VersionPurgeStatusType, +}; #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub enum ReplicationQueueAdmission { @@ -40,6 +46,116 @@ pub struct ReplicationHealQueueResult { pub admission: ReplicationQueueAdmission, } +#[derive(Debug, Clone, Default)] +pub enum ReplicationHealQueueAction { + #[default] + Skip, + QueueObject, + QueueDelete(DeletedObjectReplicationInfo), + QueueResyncDeletes(ReplicationHealResyncDeletes), +} + +#[derive(Debug, Clone, Default)] +pub struct ReplicationHealResyncDeletes { + pub delete_info: DeletedObjectReplicationInfo, + pub existing_obj_resync: ResyncDecision, +} + +impl ReplicationHealResyncDeletes { + pub fn target_delete_infos(&self) -> impl Iterator + '_ { + self.existing_obj_resync + .targets + .iter() + .filter(|(_, target)| target.replicate) + .map(|(target_arn, target)| { + let mut delete_info = self.delete_info.clone(); + delete_info.reset_id = target.reset_id.clone(); + delete_info.target_arn = target_arn.clone(); + delete_info + }) + } +} + +pub fn replication_heal_queue_action(roi: &mut ReplicateObjectInfo) -> ReplicationHealQueueAction { + if !roi.dsc.replicate_any() { + return ReplicationHealQueueAction::Skip; + } + + if roi.replication_status == ReplicationStatusType::Completed + && roi.version_purge_status.is_empty() + && !roi.existing_obj_resync.must_resync() + { + return ReplicationHealQueueAction::Skip; + } + + if roi.delete_marker || !roi.version_purge_status.is_empty() { + let delete_info = heal_deleted_object_replication_info(roi); + + if is_pending_or_failed_object_heal(roi) || is_pending_or_failed_version_purge(roi) { + return ReplicationHealQueueAction::QueueDelete(delete_info); + } + + if roi.existing_obj_resync.must_resync() + && (roi.replication_status == ReplicationStatusType::Completed || roi.replication_status.is_empty()) + { + return ReplicationHealQueueAction::QueueResyncDeletes(ReplicationHealResyncDeletes { + delete_info, + existing_obj_resync: roi.existing_obj_resync.clone(), + }); + } + + return ReplicationHealQueueAction::Skip; + } + + if roi.existing_obj_resync.must_resync() { + roi.op_type = ReplicationType::ExistingObject; + } + + if is_pending_or_failed_object_heal(roi) { + roi.event_type = REPLICATE_HEAL.to_string(); + return ReplicationHealQueueAction::QueueObject; + } + + if roi.existing_obj_resync.must_resync() { + roi.event_type = REPLICATE_EXISTING.to_string(); + return ReplicationHealQueueAction::QueueObject; + } + + ReplicationHealQueueAction::Skip +} + +fn heal_deleted_object_replication_info(roi: &ReplicateObjectInfo) -> DeletedObjectReplicationInfo { + let (version_id, delete_marker_version_id) = if roi.version_purge_status.is_empty() { + (None, roi.version_id) + } else { + (roi.version_id, None) + }; + + DeletedObjectReplicationInfo { + delete_object: DeletedObject { + object_name: roi.name.clone(), + delete_marker_version_id, + version_id, + replication_state: roi.replication_state.clone(), + delete_marker_mtime: roi.mod_time, + delete_marker: roi.delete_marker, + ..Default::default() + }, + bucket: roi.bucket.clone(), + op_type: ReplicationType::Heal, + event_type: REPLICATE_HEAL_DELETE.to_string(), + ..Default::default() + } +} + +fn is_pending_or_failed_object_heal(roi: &ReplicateObjectInfo) -> bool { + matches!(roi.replication_status, ReplicationStatusType::Pending | ReplicationStatusType::Failed) +} + +fn is_pending_or_failed_version_purge(roi: &ReplicateObjectInfo) -> bool { + matches!(roi.version_purge_status, VersionPurgeStatusType::Pending | VersionPurgeStatusType::Failed) +} + #[derive(Debug, Clone, PartialEq)] pub enum ReplicationPriority { Fast, @@ -129,9 +245,14 @@ mod tests { use std::str::FromStr; use rustfs_storage_api::DeletedObject; + use uuid::Uuid; - use super::{ReplicationOperation, ReplicationPriority, ReplicationQueueAdmission}; - use crate::{DeletedObjectReplicationInfo, ReplicateObjectInfo, ReplicationType, ReplicationWorkerOperation}; + use super::{ReplicationHealQueueAction, ReplicationOperation, ReplicationPriority, ReplicationQueueAdmission}; + use crate::{ + DeletedObjectReplicationInfo, REPLICATE_EXISTING, REPLICATE_HEAL, REPLICATE_HEAL_DELETE, ReplicateDecision, + ReplicateObjectInfo, ReplicateTargetDecision, ReplicationStatusType, ReplicationType, ReplicationWorkerOperation, + ResyncTargetDecision, VersionPurgeStatusType, replication_heal_queue_action, + }; #[test] fn replication_queue_admission_combines_target_results() { @@ -147,6 +268,102 @@ mod tests { assert_eq!(admission, ReplicationQueueAdmission::Missed); } + #[test] + fn heal_queue_action_routes_failed_objects_to_heal_queue() { + let mut roi = replicate_object_info(ReplicationStatusType::Failed); + + let action = replication_heal_queue_action(&mut roi); + + assert!(matches!(action, ReplicationHealQueueAction::QueueObject)); + assert_eq!(roi.event_type, REPLICATE_HEAL); + } + + #[test] + fn heal_queue_action_routes_existing_object_resync() { + let mut roi = replicate_object_info(ReplicationStatusType::Completed); + roi.existing_obj_resync.targets.insert( + "arn:target".to_string(), + ResyncTargetDecision { + replicate: true, + reset_id: "reset-1".to_string(), + reset_before_date: None, + }, + ); + + let action = replication_heal_queue_action(&mut roi); + + assert!(matches!(action, ReplicationHealQueueAction::QueueObject)); + assert_eq!(roi.op_type, ReplicationType::ExistingObject); + assert_eq!(roi.event_type, REPLICATE_EXISTING); + } + + #[test] + fn heal_queue_action_routes_pending_delete_marker() { + let version_id = Uuid::new_v4(); + let mut roi = replicate_object_info(ReplicationStatusType::Pending); + roi.delete_marker = true; + roi.version_id = Some(version_id); + + let action = replication_heal_queue_action(&mut roi); + + let ReplicationHealQueueAction::QueueDelete(delete_info) = action else { + panic!("expected delete queue action"); + }; + assert_eq!(delete_info.bucket, "bucket"); + assert_eq!(delete_info.event_type, REPLICATE_HEAL_DELETE); + assert_eq!(delete_info.delete_object.object_name, "object"); + assert_eq!(delete_info.delete_object.delete_marker_version_id, Some(version_id)); + assert_eq!(delete_info.delete_object.version_id, None); + } + + #[test] + fn heal_queue_action_expands_resync_delete_targets() { + let mut roi = replicate_object_info(ReplicationStatusType::Completed); + roi.delete_marker = true; + roi.existing_obj_resync.targets.insert( + "arn:replicate".to_string(), + ResyncTargetDecision { + replicate: true, + reset_id: "reset-1".to_string(), + reset_before_date: None, + }, + ); + roi.existing_obj_resync.targets.insert( + "arn:skip".to_string(), + ResyncTargetDecision { + replicate: false, + reset_id: "reset-2".to_string(), + reset_before_date: None, + }, + ); + + let action = replication_heal_queue_action(&mut roi); + + let ReplicationHealQueueAction::QueueResyncDeletes(batch) = action else { + panic!("expected resync delete queue action"); + }; + let target_deletes = batch.target_delete_infos().collect::>(); + assert_eq!(target_deletes.len(), 1); + assert_eq!(target_deletes[0].target_arn, "arn:replicate"); + assert_eq!(target_deletes[0].reset_id, "reset-1"); + } + + #[test] + fn heal_queue_action_routes_pending_version_purge() { + let version_id = Uuid::new_v4(); + let mut roi = replicate_object_info(ReplicationStatusType::Completed); + roi.version_id = Some(version_id); + roi.version_purge_status = VersionPurgeStatusType::Pending; + + let action = replication_heal_queue_action(&mut roi); + + let ReplicationHealQueueAction::QueueDelete(delete_info) = action else { + panic!("expected version purge delete queue action"); + }; + assert_eq!(delete_info.delete_object.version_id, Some(version_id)); + assert_eq!(delete_info.delete_object.delete_marker_version_id, None); + } + #[test] fn replication_priority_parses_known_values_and_defaults_unknown() { assert_eq!(ReplicationPriority::from_str("fast"), Ok(ReplicationPriority::Fast)); @@ -194,4 +411,17 @@ mod tests { assert_eq!(operation.get_size(), 128); assert_eq!(operation.get_op_type(), ReplicationType::Object); } + + fn replicate_object_info(replication_status: ReplicationStatusType) -> ReplicateObjectInfo { + let mut dsc = ReplicateDecision::new(); + dsc.set(ReplicateTargetDecision::new("arn:target".to_string(), true, false)); + + ReplicateObjectInfo { + bucket: "bucket".to_string(), + name: "object".to_string(), + replication_status, + dsc, + ..Default::default() + } + } } diff --git a/crates/replication/src/resync.rs b/crates/replication/src/resync.rs index 2bd5b2896..e174d7ed7 100644 --- a/crates/replication/src/resync.rs +++ b/crates/replication/src/resync.rs @@ -106,6 +106,10 @@ impl ResyncStatusType { } } +pub fn should_auto_resume_resync(status: ResyncStatusType) -> bool { + matches!(status, ResyncStatusType::ResyncPending | ResyncStatusType::ResyncStarted) +} + impl fmt::Display for ResyncStatusType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { @@ -543,6 +547,16 @@ mod tests { assert_eq!(ResyncStatusType::NoResync.to_string(), ""); } + #[test] + fn auto_resume_resync_only_for_inflight_states() { + assert!(should_auto_resume_resync(ResyncStatusType::ResyncPending)); + assert!(should_auto_resume_resync(ResyncStatusType::ResyncStarted)); + assert!(!should_auto_resume_resync(ResyncStatusType::NoResync)); + assert!(!should_auto_resume_resync(ResyncStatusType::ResyncCanceled)); + assert!(!should_auto_resume_resync(ResyncStatusType::ResyncCompleted)); + assert!(!should_auto_resume_resync(ResyncStatusType::ResyncFailed)); + } + #[test] fn resync_state_accepts_update_only_for_matching_run() { let current = TargetReplicationResyncStatus { diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 7b2ab7c85..c609a216f 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -2598,7 +2598,7 @@ fi ( cd "$ROOT_DIR" replication_queue_status=0 - rg -n --with-filename '^\s*(?:pub(?:\([^)]*\))?\s+)?(?:enum\s+ReplicationQueueAdmission|struct\s+ReplicationHealQueueResult|enum\s+ReplicationPriority|enum\s+ReplicationOperation)\b' \ + rg -n --with-filename '^\s*(?:pub(?:\([^)]*\))?\s+)?(?:(?:enum)\s+(?:ReplicationQueueAdmission|ReplicationHealQueueAction|ReplicationPriority|ReplicationOperation)|(?:struct)\s+(?:ReplicationHealQueueResult|ReplicationHealResyncDeletes)|fn\s+(?:replication_heal_queue_action|heal_deleted_object_replication_info|is_pending_or_failed_object_heal|is_pending_or_failed_version_purge))\b' \ crates/ecstore/src/bucket/replication \ --glob '*.rs' >"$REPLICATION_QUEUE_CONTRACT_BACKSLIDE_HITS_FILE" || replication_queue_status=$? if [[ "$replication_queue_status" -ne 0 && "$replication_queue_status" -ne 1 ]]; then @@ -2643,7 +2643,7 @@ fi ( cd "$ROOT_DIR" replication_resync_status=0 - rg -n --with-filename '^\s*(?:pub(?:\([^)]*\))?\s+)?(?:(?:struct|enum)\s+(?:ResyncOpts|TargetReplicationResyncStatus|BucketReplicationResyncStatus|ResyncStatusType)|fn\s+(?:resync_state_accepts_update|should_count_head_proxy_failure|is_version_id_mismatch))\b' \ + rg -n --with-filename '^\s*(?:pub(?:\([^)]*\))?\s+)?(?:(?:struct|enum)\s+(?:ResyncOpts|TargetReplicationResyncStatus|BucketReplicationResyncStatus|ResyncStatusType)|fn\s+(?:resync_state_accepts_update|should_count_head_proxy_failure|should_auto_resume_resync|is_version_id_mismatch))\b' \ crates/ecstore/src/bucket/replication \ --glob '*.rs' >"$REPLICATION_RESYNC_CONTRACT_BACKSLIDE_HITS_FILE" || replication_resync_status=$? if [[ "$replication_resync_status" -ne 0 && "$replication_resync_status" -ne 1 ]]; then