mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 13:16:28 +00:00
refactor(replication): isolate storage api contracts (#4240)
* refactor(replication): isolate storage api contracts * docs(replication): record storage api contract boundary
This commit is contained in:
@@ -37,6 +37,7 @@ paths.
|
|||||||
| `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. |
|
| `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. |
|
||||||
| `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`. |
|
| `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`. |
|
||||||
| `ReplicationFileMeta` | Replication status, decisions, MRF entries, resync decisions, and target reset helpers. | `rustfs_filemeta` replication contracts are concentrated in `replication_filemeta_boundary.rs`; `FileInfo` remains in the storage boundary for storage trait bindings and walk options. |
|
| `ReplicationFileMeta` | Replication status, decisions, MRF entries, resync decisions, and target reset helpers. | `rustfs_filemeta` replication contracts are concentrated in `replication_filemeta_boundary.rs`; `FileInfo` remains in the storage boundary for storage trait bindings and walk options. |
|
||||||
|
| `StorageApiReplicationContracts` | Storage-api delete DTO replication state/status helpers. | The temporary `rustfs-filemeta` dependency is isolated in `crates/storage-api/src/replication.rs` until the wire contracts can move without creating a `rustfs-replication` / `rustfs-storage-api` cycle. |
|
||||||
| `ReplicationObjectDecisionContracts` | Object replication options, delete replication decisions, resync target projection, multipart planning, and delete-marker retry classifiers. | Owned by `crates/replication`; ECStore imports them through `replication_object_decision_boundary.rs`. |
|
| `ReplicationObjectDecisionContracts` | Object replication options, delete replication decisions, resync target projection, multipart planning, and delete-marker retry classifiers. | Owned by `crates/replication`; ECStore imports them through `replication_object_decision_boundary.rs`. |
|
||||||
| `ReplicationQueueContracts` | Queue admission, heal queue results/actions, worker operations, worker sizing, and backpressure decisions. | Owned by `crates/replication`; ECStore imports them through `replication_queue_boundary.rs`. |
|
| `ReplicationQueueContracts` | Queue admission, heal queue results/actions, worker operations, worker sizing, and backpressure decisions. | Owned by `crates/replication`; ECStore imports them through `replication_queue_boundary.rs`. |
|
||||||
| `ReplicationStatsContracts` | Bucket stats, replication target stats, queue/proxy metrics, and worker metric snapshots. | Owned by `crates/replication`; ECStore imports them through `replication_stats_boundary.rs`. |
|
| `ReplicationStatsContracts` | Bucket stats, replication target stats, queue/proxy metrics, and worker metric snapshots. | Owned by `crates/replication`; ECStore imports them through `replication_stats_boundary.rs`. |
|
||||||
@@ -82,6 +83,10 @@ paths.
|
|||||||
compatibility facade.
|
compatibility facade.
|
||||||
10. Keep ECStore owner modules outside `bucket/replication` behind bridge
|
10. Keep ECStore owner modules outside `bucket/replication` behind bridge
|
||||||
contracts when they need replication codec or config helper behavior.
|
contracts when they need replication codec or config helper behavior.
|
||||||
|
11. Keep storage-api replication status/state helpers behind
|
||||||
|
`crates/storage-api/src/replication.rs` until the underlying wire contracts
|
||||||
|
can move without a `rustfs-replication` / `rustfs-storage-api` dependency
|
||||||
|
cycle.
|
||||||
|
|
||||||
## First Code-Bearing Step
|
## First Code-Bearing Step
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,8 @@ doctest = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
# NOTE: This dependency on rustfs-filemeta is a known architectural limitation.
|
# Storage-facing replication contracts are isolated in src/replication.rs until
|
||||||
# The replication types (ReplicationStatusType, VersionPurgeStatusType, ReplicationState)
|
# the underlying wire types can move without creating a replication/storage-api cycle.
|
||||||
# are shared between storage-api and filemeta. Moving them would require changes in 300+ files.
|
|
||||||
rustfs-filemeta.workspace = true
|
rustfs-filemeta.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
time.workspace = true
|
time.workspace = true
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ pub mod object;
|
|||||||
pub mod observability;
|
pub mod observability;
|
||||||
pub mod topology;
|
pub mod topology;
|
||||||
|
|
||||||
|
mod replication;
|
||||||
|
|
||||||
pub use admin::{DiskSetSelector, StorageAdminApi};
|
pub use admin::{DiskSetSelector, StorageAdminApi};
|
||||||
pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};
|
pub use bucket::{BucketInfo, BucketOperations, BucketOptions, DeleteBucketOptions, MakeBucketOptions, SRBucketDeleteOp};
|
||||||
pub use capability::{CapabilitySnapshotError, CapabilityState, CapabilityStatus};
|
pub use capability::{CapabilitySnapshotError, CapabilityState, CapabilityStatus};
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustfs_filemeta::{
|
use crate::replication::{
|
||||||
ReplicationState, ReplicationStatusType, VersionPurgeStatusType, replication_statuses_map, version_purge_statuses_map,
|
ReplicationState, ReplicationStatusType, VersionPurgeStatusType, replication_statuses_map, version_purge_statuses_map,
|
||||||
};
|
};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2024 RustFS Team
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
pub(crate) use rustfs_filemeta::{
|
||||||
|
ReplicationState, ReplicationStatusType, VersionPurgeStatusType, replication_statuses_map, version_purge_statuses_map,
|
||||||
|
};
|
||||||
@@ -29,6 +29,12 @@ Contract crates must stay below implementation crates. Initial forbidden edges:
|
|||||||
- `extension-schema -> rustfs`
|
- `extension-schema -> rustfs`
|
||||||
- `extension-schema -> ecstore`
|
- `extension-schema -> ecstore`
|
||||||
|
|
||||||
|
`rustfs-storage-api` may only expose storage-facing replication status/state
|
||||||
|
contracts through `crates/storage-api/src/replication.rs` while the underlying
|
||||||
|
wire types still live in `rustfs-filemeta`. This keeps the temporary dependency
|
||||||
|
centralized until those wire contracts can move without introducing a
|
||||||
|
`rustfs-replication` / `rustfs-storage-api` cycle.
|
||||||
|
|
||||||
Existing migration checks live in:
|
Existing migration checks live in:
|
||||||
|
|
||||||
- `scripts/check_layer_dependencies.sh`
|
- `scripts/check_layer_dependencies.sh`
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ Current coupling:
|
|||||||
- resync options, bucket/target resync status DTOs, status display labels, and
|
- resync options, bucket/target resync status DTOs, status display labels, and
|
||||||
the persisted resync status wire format live in `crates/replication`, with
|
the persisted resync status wire format live in `crates/replication`, with
|
||||||
ECStore retaining only error mapping and MRF persistence locally;
|
ECStore retaining only error mapping and MRF persistence locally;
|
||||||
|
- 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`;
|
||||||
- admin replication extension target filtering and resync request construction
|
- admin replication extension target filtering and resync request construction
|
||||||
stay behind the admin storage boundary instead of exposing replication work
|
stay behind the admin storage boundary instead of exposing replication work
|
||||||
DTO construction to handlers;
|
DTO construction to handlers;
|
||||||
@@ -168,6 +171,10 @@ Required contracts before crate movement:
|
|||||||
`crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs`,
|
`crates/ecstore/src/bucket/replication/replication_filemeta_boundary.rs`,
|
||||||
while `FileInfo` remains in the storage boundary for storage trait bindings
|
while `FileInfo` remains in the storage boundary for storage trait bindings
|
||||||
and walk options.
|
and walk options.
|
||||||
|
- `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
|
||||||
|
`rustfs-replication` / `rustfs-storage-api` dependency cycle.
|
||||||
- `ReplicationErrorBoundary`: ECStore error/result contracts and
|
- `ReplicationErrorBoundary`: ECStore error/result contracts and
|
||||||
replication-specific error classifiers. `crate::error` imports are
|
replication-specific error classifiers. `crate::error` imports are
|
||||||
concentrated in
|
concentrated in
|
||||||
|
|||||||
@@ -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/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/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" "ecstore-api-facade-inventory.md" "ECStore split plan facade inventory link"
|
||||||
|
require_source_contains "docs/architecture/ecstore-module-split-plan.md" "StorageApiReplicationContracts" "ECStore split plan storage-api replication contract section"
|
||||||
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## Facade Group Inventory" "ECStore facade inventory group section"
|
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## Facade Group Inventory" "ECStore facade inventory group section"
|
||||||
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## External Consumer Boundaries" "ECStore facade inventory consumer boundary section"
|
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## External Consumer Boundaries" "ECStore facade inventory consumer boundary section"
|
||||||
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## Split Dependency Inventory" "ECStore split dependency inventory section"
|
require_source_contains "docs/architecture/ecstore-api-facade-inventory.md" "## Split Dependency Inventory" "ECStore split dependency inventory section"
|
||||||
@@ -138,6 +139,7 @@ LIFECYCLE_OBJECT_LOCK_BOUNDARY_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_object_loc
|
|||||||
LIFECYCLE_REPLICATION_SINK_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_replication_sink_bypass_hits.txt"
|
LIFECYCLE_REPLICATION_SINK_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_replication_sink_bypass_hits.txt"
|
||||||
LIFECYCLE_REPLICATION_CRATE_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_replication_crate_bypass_hits.txt"
|
LIFECYCLE_REPLICATION_CRATE_BYPASS_HITS_FILE="${TMP_DIR}/lifecycle_replication_crate_bypass_hits.txt"
|
||||||
ECSTORE_REPLICATION_CONTRACT_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_replication_contract_bypass_hits.txt"
|
ECSTORE_REPLICATION_CONTRACT_BYPASS_HITS_FILE="${TMP_DIR}/ecstore_replication_contract_bypass_hits.txt"
|
||||||
|
STORAGE_API_REPLICATION_CONTRACT_BYPASS_HITS_FILE="${TMP_DIR}/storage_api_replication_contract_bypass_hits.txt"
|
||||||
STORE_API_EXTERNAL_LIST_CONSUMER_HITS_FILE="${TMP_DIR}/store_api_external_list_consumer_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_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"
|
STORE_API_OBJECT_OPERATION_LOCAL_METHOD_HITS_FILE="${TMP_DIR}/store_api_object_operation_local_method_hits.txt"
|
||||||
@@ -972,6 +974,18 @@ if [[ -s "$ECSTORE_REPLICATION_CONTRACT_BYPASS_HITS_FILE" ]]; then
|
|||||||
report_failure "ECStore owner replication contracts must stay behind crates/ecstore/src/bucket/replication: $(paste -sd '; ' "$ECSTORE_REPLICATION_CONTRACT_BYPASS_HITS_FILE")"
|
report_failure "ECStore owner replication contracts must stay behind crates/ecstore/src/bucket/replication: $(paste -sd '; ' "$ECSTORE_REPLICATION_CONTRACT_BYPASS_HITS_FILE")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
rg -n -U --with-filename 'use\s+rustfs_filemeta::\{[^}]*\b(ReplicationState|ReplicationStatusType|VersionPurgeStatusType|replication_statuses_map|version_purge_statuses_map)\b|use\s+rustfs_filemeta::(ReplicationState|ReplicationStatusType|VersionPurgeStatusType|replication_statuses_map|version_purge_statuses_map)\b|rustfs_filemeta::(Replication|VersionPurge|replication_statuses_map|version_purge_statuses_map)' \
|
||||||
|
crates/storage-api/src \
|
||||||
|
--glob '*.rs' |
|
||||||
|
rg -v '^crates/storage-api/src/replication\.rs:' || true
|
||||||
|
) >"$STORAGE_API_REPLICATION_CONTRACT_BYPASS_HITS_FILE"
|
||||||
|
|
||||||
|
if [[ -s "$STORAGE_API_REPLICATION_CONTRACT_BYPASS_HITS_FILE" ]]; then
|
||||||
|
report_failure "storage-api replication contracts must stay behind crates/storage-api/src/replication.rs: $(paste -sd '; ' "$STORAGE_API_REPLICATION_CONTRACT_BYPASS_HITS_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
(
|
(
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
rg -n --no-heading 'rustfs_ecstore::store_api(?:::\{[^}]*\b(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b|::(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b)' \
|
rg -n --no-heading 'rustfs_ecstore::store_api(?:::\{[^}]*\b(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b|::(?:ListObjectVersionsInfo|ListObjectsV2Info|ObjectInfoOrErr)\b)' \
|
||||||
|
|||||||
Reference in New Issue
Block a user