mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-17 10:17:55 +00:00
6cf9cf7bb5
* chore(ecstore): drop the bucket dead_code blanket The last blanket of the backlog#1823 burn-down, and the largest: 71 items across lifecycle, replication, metadata, quota, object lock and bucket utils. Four are deleted. Deleted, all trivial: - check_valid_object_name and check_valid_object_name_prefix, a pair that only calls into each other with no external caller. Worth stating plainly so nobody reads this as a validation gap: object names are validated through check_object_name_for_length_and_slash, which is live; this pair is a second, unwired entry point. - DEFAULT_HEALTH_CHECK_RELOAD_DURATION, a lone unused constant. - The LifecycleReplicationConfig alias, which orphaned a re-export in replication/mod.rs that goes with it. Everything else is kept, in four groups, because the blanket here was hiding structure rather than rot: Windows platform gating. WINDOWS_RESERVED_NAMES, the two reason constants and object_name_has_windows_incompatible_segment are called from inside the #[cfg(target_os = "windows")] block in check_object_name_for_length_and_slash (utils.rs:228-255), so they only read as dead on non-Windows hosts. As with the Linux gating in the disk root, this cannot be adjudicated locally: cargo check for both x86_64-pc-windows-msvc and x86_64-unknown-linux-gnu fails in the aws-lc-sys build script for want of a cross C toolchain. CI covers both. Declared boundary surface. The *_boundary.rs and *_bridge.rs files carry the replication split plan's contracts, which scripts/check_architecture_migration_rules.sh pins through the EcstoreReplicationBoundaryImports section of the split-plan doc. Their unused items are declarations, not leftovers. test-util seams. ConfigWriteLockProbe with install/wait_until_attempted follows the same pattern as the barriers in the services and set_disk roots. MinIO-parity tier/lifecycle entry points that this port never wired: apply_lifecycle_action, get_transitioned_object_reader, recover_tier_free_versions, delete_object_from_remote_tier, abort_tier_delete_journal_entry and the replication pool's worker-management surface. These are complete, substantial machinery with no caller — the same shape as data_usage's local_snapshot feature. Removing them is a product decision, so they are made explicit here rather than deleted. Verification, four lanes warning-free: default, --tests, --features rio-v2 --tests, --features test-util --tests. cargo nextest run -p rustfs-ecstore 4096 passed; clippy --lib --tests -D warnings clean; make pre-commit exit 0. Note that clippy is what caught the orphaned re-export above: cargo check and pre-commit both treat unused_imports as a warning. Ref rustfs/backlog#1823 (step 2, final root). * chore(ecstore): correct inaccurate dead_code reasons in the bucket root Six items were labelled 'asserted by this file's tests' or as MinIO-parity entry points while having no caller at all - free get_bucket_acl_config and created_at only reach their own live methods (production goes through created_at_in), BucketVersioningSys::get_in, utils::serialize_content and ServiceType have no reference anywhere, and with_transition_queue_env_async is an unused test fixture, not a tier entry point. Name what each one is so the next reader does not assume coverage that is not there. Ref rustfs/backlog#1823.
147 lines
5.6 KiB
Rust
147 lines
5.6 KiB
Rust
// 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.
|
|
|
|
use s3s::dto::ReplicationConfiguration;
|
|
|
|
use super::replication_config_boundary::ReplicationConfigurationExt as _;
|
|
use super::replication_filemeta_boundary::{
|
|
REPLICATE_INCOMING_DELETE, ReplicateDecision, ReplicationState, version_purge_statuses_map,
|
|
};
|
|
use super::replication_object_config::{ReplicationConfig, check_replicate_delete};
|
|
use super::replication_queue_boundary::DeletedObjectReplicationInfo;
|
|
use super::replication_storage_boundary::{
|
|
DeletedObject, ObjectInfo, ObjectOptions, ObjectToDelete, deleted_object_for_replication,
|
|
};
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) type ReplicationLifecycleConfig = ReplicationConfig;
|
|
|
|
pub(crate) struct ReplicationLifecycleBridge;
|
|
|
|
impl ReplicationLifecycleBridge {
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) fn new_config(config: ReplicationConfiguration) -> ReplicationLifecycleConfig {
|
|
ReplicationConfig::new(Some(config), None)
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) fn has_pending_version_purge(
|
|
config: &ReplicationLifecycleConfig,
|
|
object_name: &str,
|
|
version_purge_pending: bool,
|
|
) -> bool {
|
|
version_purge_pending
|
|
&& config
|
|
.config
|
|
.as_ref()
|
|
.is_some_and(|config| config.has_active_rules(object_name, true))
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) async fn check_delete_replication(
|
|
bucket: &str,
|
|
object: &ObjectToDelete,
|
|
source: &ObjectInfo,
|
|
opts: &ObjectOptions,
|
|
) -> ReplicateDecision {
|
|
check_replicate_delete(bucket, object, source, opts, None).await
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "declared boundary surface for the ECStore replication split plan; no caller in this port (backlog#1823)"
|
|
)]
|
|
pub(crate) fn version_delete_replication_state(decision: &ReplicateDecision) -> ReplicationState {
|
|
let pending_status = decision.pending_status();
|
|
ReplicationState {
|
|
replicate_decision_str: decision.to_string(),
|
|
version_purge_status_internal: pending_status.clone(),
|
|
purge_targets: version_purge_statuses_map(pending_status.as_deref().unwrap_or_default()),
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
pub(crate) async fn schedule_delete(bucket: String, delete_object: DeletedObject) {
|
|
super::replication_pool::schedule_replication_delete(DeletedObjectReplicationInfo {
|
|
delete_object: deleted_object_for_replication(delete_object),
|
|
bucket,
|
|
event_type: REPLICATE_INCOMING_DELETE.to_string(),
|
|
..Default::default()
|
|
})
|
|
.await;
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use s3s::dto::{Destination, ReplicationRule, ReplicationRuleStatus};
|
|
|
|
use super::super::replication_filemeta_boundary::{ReplicateTargetDecision, VersionPurgeStatusType};
|
|
use super::*;
|
|
|
|
fn replication_rule() -> ReplicationRule {
|
|
ReplicationRule {
|
|
delete_marker_replication: None,
|
|
delete_replication: None,
|
|
destination: Destination {
|
|
bucket: "arn:aws:s3:::target-bucket".to_string(),
|
|
..Default::default()
|
|
},
|
|
existing_object_replication: None,
|
|
filter: None,
|
|
id: Some("rule".to_string()),
|
|
prefix: Some(String::new()),
|
|
priority: Some(1),
|
|
source_selection_criteria: None,
|
|
status: ReplicationRuleStatus::from_static(ReplicationRuleStatus::ENABLED),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn has_pending_version_purge_preserves_replication_active_rule_behavior() {
|
|
let config = ReplicationLifecycleBridge::new_config(ReplicationConfiguration {
|
|
role: String::new(),
|
|
rules: vec![replication_rule()],
|
|
});
|
|
|
|
assert!(ReplicationLifecycleBridge::has_pending_version_purge(&config, "logs/object", true));
|
|
assert!(!ReplicationLifecycleBridge::has_pending_version_purge(&config, "logs/object", false));
|
|
}
|
|
|
|
#[test]
|
|
fn version_delete_replication_state_tracks_pending_purge_targets() {
|
|
let target = ReplicateTargetDecision::new("arn:aws:s3:::target".to_string(), true, false);
|
|
let mut decision = ReplicateDecision::new();
|
|
decision.set(target);
|
|
|
|
let state = ReplicationLifecycleBridge::version_delete_replication_state(&decision);
|
|
|
|
assert_eq!(state.version_purge_status_internal.as_deref(), Some("arn:aws:s3:::target=PENDING;"));
|
|
assert!(state.purge_targets.contains_key("arn:aws:s3:::target"));
|
|
assert_eq!(state.purge_targets["arn:aws:s3:::target"], VersionPurgeStatusType::Pending);
|
|
}
|
|
}
|