diff --git a/crates/ecstore/src/bucket/replication/README.md b/crates/ecstore/src/bucket/replication/README.md index c0e28ea80..366d84115 100644 --- a/crates/ecstore/src/bucket/replication/README.md +++ b/crates/ecstore/src/bucket/replication/README.md @@ -34,6 +34,7 @@ paths. | `ReplicationObjectIO` | Object read/write primitives used by config, MRF, resync status, and multipart replication paths. | ECStore object API reader/writer types and storage-api object IO contracts are concentrated in `replication_storage_boundary.rs`. | | `ReplicationStorage` | Object read/write/delete, object walk, metadata update, and target object IO. | ECStore object API, storage-api contracts, and read option types are concentrated in `replication_storage_boundary.rs`. | | `ReplicationMetadataStore` | Replication config, MRF/resync state, target reset headers, and status persistence. | Metadata sys access and replication metadata path constants are exposed through the contract type in `replication_metadata_boundary.rs`; versioning sys and config storage imports remain separate contracts. | +| `EcstoreReplicationBoundaryImports` | ECStore-side imports from `rustfs-replication`. | Direct `rustfs-replication` imports under `crates/ecstore/src/bucket/replication` stay in `*_boundary.rs` modules, including config and resync facade re-exports. | | `ReplicationResyncContracts` | Resync options, target status, bucket status, status classifiers, and persisted resync/MRF status wire format. | Owned by `crates/replication`; ECStore imports them through `replication_resync_boundary.rs`, which maps crate errors to ECStore errors. | | `ReplicationCrateFileMetaFacade` | Replication facade compatibility symbols that still originate in filemeta wire contracts. | `crates/replication/src/filemeta.rs` is the only direct `rustfs-filemeta` import boundary inside `rustfs-replication`. | | `ReplicationConfigStore` | Replication config persistence and config-derived labels used by target options. | Config read/save helpers and storage class labels are exposed through the contract type in `replication_config_store.rs`. | @@ -93,6 +94,8 @@ paths. concentrated in `crates/replication/src/filemeta.rs`. 13. Keep direct `rustfs-storage-api` imports inside `rustfs-replication` concentrated in `crates/replication/src/storage_api.rs`. +14. Keep direct `rustfs-replication` imports inside ECStore replication + concentrated in `*_boundary.rs` modules. ## First Code-Bearing Step diff --git a/crates/ecstore/src/bucket/replication/datatypes.rs b/crates/ecstore/src/bucket/replication/datatypes.rs index 83758ff09..005a47966 100644 --- a/crates/ecstore/src/bucket/replication/datatypes.rs +++ b/crates/ecstore/src/bucket/replication/datatypes.rs @@ -12,4 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use rustfs_replication::ResyncStatusType; +pub use super::replication_resync_boundary::ResyncStatusType; diff --git a/crates/ecstore/src/bucket/replication/mod.rs b/crates/ecstore/src/bucket/replication/mod.rs index e640a221e..d129b1551 100644 --- a/crates/ecstore/src/bucket/replication/mod.rs +++ b/crates/ecstore/src/bucket/replication/mod.rs @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod config; pub mod datatypes; mod replication_bandwidth_boundary; +mod replication_config_boundary; mod replication_config_store; mod replication_error_boundary; mod replication_event_sink; @@ -42,8 +42,8 @@ mod replication_target_config_bridge; mod replication_versioning_boundary; mod runtime_boundary; -pub use config::{ObjectOpts, ReplicationConfigurationExt}; pub use datatypes::ResyncStatusType; +pub use replication_config_boundary::{ObjectOpts, ReplicationConfigurationExt}; #[cfg(test)] pub(crate) use replication_filemeta_boundary::ReplicateTargetDecision; pub(crate) use replication_filemeta_boundary::{ diff --git a/crates/ecstore/src/bucket/replication/config.rs b/crates/ecstore/src/bucket/replication/replication_config_boundary.rs similarity index 100% rename from crates/ecstore/src/bucket/replication/config.rs rename to crates/ecstore/src/bucket/replication/replication_config_boundary.rs diff --git a/crates/ecstore/src/bucket/replication/replication_lifecycle_bridge.rs b/crates/ecstore/src/bucket/replication/replication_lifecycle_bridge.rs index e24ceba5c..73f3d89ef 100644 --- a/crates/ecstore/src/bucket/replication/replication_lifecycle_bridge.rs +++ b/crates/ecstore/src/bucket/replication/replication_lifecycle_bridge.rs @@ -14,7 +14,7 @@ use s3s::dto::ReplicationConfiguration; -use super::config::ReplicationConfigurationExt as _; +use super::replication_config_boundary::ReplicationConfigurationExt as _; use super::replication_filemeta_boundary::{ REPLICATE_INCOMING_DELETE, ReplicateDecision, ReplicationState, version_purge_statuses_map, }; diff --git a/crates/ecstore/src/bucket/replication/replication_object_config.rs b/crates/ecstore/src/bucket/replication/replication_object_config.rs index 3bee947ff..803b898fe 100644 --- a/crates/ecstore/src/bucket/replication/replication_object_config.rs +++ b/crates/ecstore/src/bucket/replication/replication_object_config.rs @@ -19,7 +19,7 @@ use s3s::dto::ReplicationConfiguration; use serde::{Deserialize, Serialize}; use tracing::error; -use super::config::{ObjectOpts, ReplicationConfigurationExt as _}; +use super::replication_config_boundary::{ObjectOpts, ReplicationConfigurationExt as _}; use super::replication_error_boundary::Result; use super::replication_filemeta_boundary::{ ReplicateDecision, ReplicateTargetDecision, ReplicationStatusType, ReplicationType, ResyncDecision, diff --git a/crates/ecstore/src/bucket/replication/replication_pool.rs b/crates/ecstore/src/bucket/replication/replication_pool.rs index b54c6af4a..62977247d 100644 --- a/crates/ecstore/src/bucket/replication/replication_pool.rs +++ b/crates/ecstore/src/bucket/replication/replication_pool.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::datatypes::ResyncStatusType; use super::replication_config_store::ReplicationConfigStore; use super::replication_error_boundary::Error as EcstoreError; use super::replication_filemeta_boundary::{ @@ -30,6 +29,7 @@ use super::replication_queue_boundary::{ initial_worker_counts, large_worker_backpressure_resize, mrf_worker_size_to_count, replication_backpressure_recommendation, replication_heal_queue_action, resized_worker_counts, should_queue_large_object, worker_queue_for_replication_type, }; +use super::replication_resync_boundary::ResyncStatusType; use super::replication_resync_boundary::{ BucketReplicationResyncStatus, ResyncOpts, TargetReplicationResyncStatus, decode_mrf_file, decode_resync_file, encode_mrf_file, should_auto_resume_resync, diff --git a/crates/ecstore/src/bucket/replication/replication_resync_boundary.rs b/crates/ecstore/src/bucket/replication/replication_resync_boundary.rs index c237654a3..7df357ad3 100644 --- a/crates/ecstore/src/bucket/replication/replication_resync_boundary.rs +++ b/crates/ecstore/src/bucket/replication/replication_resync_boundary.rs @@ -15,7 +15,7 @@ use super::replication_error_boundary::{Error, Result}; use super::replication_filemeta_boundary::MrfReplicateEntry; -pub use rustfs_replication::{BucketReplicationResyncStatus, ResyncOpts, TargetReplicationResyncStatus}; +pub use rustfs_replication::{BucketReplicationResyncStatus, ResyncOpts, ResyncStatusType, TargetReplicationResyncStatus}; pub(crate) use rustfs_replication::{ is_version_id_mismatch, resync_state_accepts_update, should_auto_resume_resync, should_count_head_proxy_failure, }; diff --git a/crates/ecstore/src/bucket/replication/replication_resyncer.rs b/crates/ecstore/src/bucket/replication/replication_resyncer.rs index d1736249c..98daaf4bb 100644 --- a/crates/ecstore/src/bucket/replication/replication_resyncer.rs +++ b/crates/ecstore/src/bucket/replication/replication_resyncer.rs @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::config::{ObjectOpts, ReplicationConfigurationExt as _}; -use super::datatypes::ResyncStatusType; use super::replication_bandwidth_boundary; +use super::replication_config_boundary::{ObjectOpts, ReplicationConfigurationExt as _}; use super::replication_config_store::ReplicationConfigStore; use super::replication_error_boundary::{Result, is_err_object_not_found, is_err_version_not_found}; use super::replication_event_sink::{EventArgs, send_event, send_local_event}; @@ -35,6 +34,7 @@ use super::replication_object_decision_boundary::{ replication_multipart_complete_actual_size, replication_multipart_part_plan, should_retry_delete_marker_purge, }; use super::replication_queue_boundary::DeletedObjectReplicationInfo; +use super::replication_resync_boundary::ResyncStatusType; use super::replication_resync_boundary::{ BucketReplicationResyncStatus, ResyncOpts, TargetReplicationResyncStatus, encode_resync_file, is_version_id_mismatch, resync_state_accepts_update, should_count_head_proxy_failure, diff --git a/crates/ecstore/src/bucket/replication/replication_target_config_bridge.rs b/crates/ecstore/src/bucket/replication/replication_target_config_bridge.rs index 80230772f..8dcc6ae2d 100644 --- a/crates/ecstore/src/bucket/replication/replication_target_config_bridge.rs +++ b/crates/ecstore/src/bucket/replication/replication_target_config_bridge.rs @@ -14,7 +14,7 @@ use s3s::dto::ReplicationConfiguration; -use super::config::{ObjectOpts, ReplicationConfigurationExt}; +use super::replication_config_boundary::{ObjectOpts, ReplicationConfigurationExt}; use super::replication_filemeta_boundary::ReplicationType; pub(crate) struct ReplicationTargetConfigBridge; diff --git a/docs/architecture/ecstore-module-split-plan.md b/docs/architecture/ecstore-module-split-plan.md index 110acc44f..e19cbc5b9 100644 --- a/docs/architecture/ecstore-module-split-plan.md +++ b/docs/architecture/ecstore-module-split-plan.md @@ -129,6 +129,8 @@ Current coupling: import boundary inside `rustfs-replication`; - `crates/replication/src/storage_api.rs` is the only direct storage-api delete DTO import boundary inside `rustfs-replication`; +- direct ECStore replication imports from `rustfs-replication` are limited to + `*_boundary.rs` modules; - storage-api delete replication status/state helpers use the local `crates/storage-api/src/replication.rs` contract boundary while the underlying wire types remain in `rustfs-filemeta`; @@ -181,6 +183,8 @@ Required contracts before crate movement: - `ReplicationCrateStorageApiBoundary`: storage API delete DTOs consumed by replication delete/queue/operation helpers are concentrated in `crates/replication/src/storage_api.rs` inside `rustfs-replication`. +- `EcstoreReplicationBoundaryImports`: ECStore-side imports from + `rustfs-replication` are concentrated in replication `*_boundary.rs` modules. - `StorageApiReplicationContracts`: storage-api delete DTO replication state/status helpers are concentrated in `crates/storage-api/src/replication.rs` until the underlying wire contracts can move without a diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 3012894cd..c5aef38cd 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -84,6 +84,7 @@ require_source_contains "docs/architecture/obs-ecstore-dependency-inventory.md" require_source_contains "docs/architecture/obs-ecstore-dependency-inventory.md" "crates/obs/src/metrics/storage_api.rs" "observability ECStore storage_api boundary" require_source_contains "docs/architecture/overview.md" "ecstore-api-facade-inventory.md" "architecture overview ECStore facade inventory link" require_source_contains "docs/architecture/ecstore-module-split-plan.md" "ecstore-api-facade-inventory.md" "ECStore split plan facade inventory link" +require_source_contains "docs/architecture/ecstore-module-split-plan.md" "EcstoreReplicationBoundaryImports" "ECStore split plan replication boundary imports section" require_source_contains "docs/architecture/ecstore-module-split-plan.md" "ReplicationCrateFileMetaFacade" "ECStore split plan replication crate filemeta facade section" require_source_contains "docs/architecture/ecstore-module-split-plan.md" "ReplicationCrateStorageApiBoundary" "ECStore split plan replication crate storage-api boundary section" require_source_contains "docs/architecture/ecstore-module-split-plan.md" "StorageApiReplicationContracts" "ECStore split plan storage-api replication contract section" @@ -205,6 +206,7 @@ FUZZ_ECSTORE_COMPAT_BYPASS_HITS_FILE="${TMP_DIR}/fuzz_ecstore_compat_bypass_hits EXTERNAL_ECSTORE_API_BOUNDARY_HITS_FILE="${TMP_DIR}/external_ecstore_api_boundary_hits.txt" REPLICATION_FACADE_BYPASS_HITS_FILE="${TMP_DIR}/replication_facade_bypass_hits.txt" REPLICATION_FACADE_WILDCARD_EXPORT_HITS_FILE="${TMP_DIR}/replication_facade_wildcard_export_hits.txt" +ECSTORE_REPLICATION_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_replication_boundary_bypass_hits.txt" REPLICATION_CRATE_FILEMETA_BYPASS_HITS_FILE="${TMP_DIR}/replication_crate_filemeta_bypass_hits.txt" REPLICATION_CRATE_STORAGE_API_BYPASS_HITS_FILE="${TMP_DIR}/replication_crate_storage_api_bypass_hits.txt" REPLICATION_CONFIG_RULE_CONTRACT_BACKSLIDE_HITS_FILE="${TMP_DIR}/replication_config_rule_contract_backslide_hits.txt" @@ -2611,6 +2613,18 @@ if [[ -s "$REPLICATION_FACADE_WILDCARD_EXPORT_HITS_FILE" ]]; then report_failure "replication facade must use explicit compatibility exports instead of wildcard re-exports: $(paste -sd '; ' "$REPLICATION_FACADE_WILDCARD_EXPORT_HITS_FILE")" fi +( + cd "$ROOT_DIR" + rg -n --with-filename 'rustfs_replication::|use\s+rustfs_replication\b' \ + crates/ecstore/src/bucket/replication \ + --glob '*.rs' | + rg -v '^crates/ecstore/src/bucket/replication/[^:]*_boundary\.rs:' || true +) >"$ECSTORE_REPLICATION_BOUNDARY_BYPASS_HITS_FILE" + +if [[ -s "$ECSTORE_REPLICATION_BOUNDARY_BYPASS_HITS_FILE" ]]; then + report_failure "ECStore replication rustfs-replication imports must stay behind *_boundary.rs modules: $(paste -sd '; ' "$ECSTORE_REPLICATION_BOUNDARY_BYPASS_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --with-filename 'rustfs_filemeta::|use\s+rustfs_filemeta\b' \