mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-29 16:37:07 +00:00
fix(scanner): fence movement generation publication (#6461)
* feat(scanner): add movement generation fencing * fix(scanner): prioritize unverified cycle deferral * feat(ecstore): add scanner publication lease fence * feat(rpc): add scanner publication lease protocol * feat(scanner): hold remote leases through usage publish * test(scanner): cover publication lease fencing * fix(scanner): fence remote leases across restart and delay * feat(rpc): fence scanner publication rename writes * fix(scanner): fence observed cleanup deletes * fix(proto): qualify lease release test types * fix(scanner): pin movement notifications * fix(scanner): clean publication imports * fix(ecstore): satisfy scanner fence clippy * refactor(scanner): group wait and publication options * fix(scanner): satisfy final lint and facade guards * fix(rpc): resolve facade export conflicts * fix(ci): remove unused decommission and healing facades * fix(ci): cfg-gate test-only usage overlay import * fix(scanner): wake on remote scanner restart
This commit is contained in:
@@ -151,7 +151,8 @@ impl ScannerIOCycle for ECStore {
|
||||
ScannerCycleResult::new(ScannerCycleStatus::Incomplete, None).with_publication_epoch(publication_epoch)
|
||||
);
|
||||
}
|
||||
let activity_status = scanner_cycle_activity_status(self, distributed, &activity_before).await;
|
||||
let (activity_status, remote_publication_lease_targets) =
|
||||
scanner_cycle_activity_status(self, distributed, &activity_before).await;
|
||||
let dirty_usage_status = dirty_usage_snapshot_status(&dirty_usage_snapshot);
|
||||
let status = classify_nsscanner_cycle(
|
||||
true,
|
||||
@@ -187,6 +188,7 @@ impl ScannerIOCycle for ECStore {
|
||||
};
|
||||
return Ok(ScannerCycleResult::new(status, dirty_usage_clear)
|
||||
.with_publication_epoch(publication_epoch)
|
||||
.with_remote_publication_lease_targets(remote_publication_lease_targets)
|
||||
.with_remote_dirty_usage_acknowledgements(remote_dirty_usage_acknowledgements));
|
||||
}
|
||||
|
||||
@@ -400,7 +402,8 @@ impl ScannerIOCycle for ECStore {
|
||||
let budget_elapsed = budget.budget_elapsed();
|
||||
let dirty_usage_status = dirty_usage_snapshot_status(&dirty_usage_snapshot);
|
||||
let dirty_usage_current = dirty_usage_status == DirtyUsageSnapshotStatus::Current;
|
||||
let activity_status = scanner_cycle_activity_status(self, distributed, &activity_before).await;
|
||||
let (activity_status, remote_publication_lease_targets) =
|
||||
scanner_cycle_activity_status(self, distributed, &activity_before).await;
|
||||
let all_bucket_names = all_buckets.iter().map(|bucket| bucket.name.clone()).collect::<Vec<_>>();
|
||||
let completed_usage = completed_data_usage_info(
|
||||
&results,
|
||||
@@ -460,6 +463,7 @@ impl ScannerIOCycle for ECStore {
|
||||
};
|
||||
Ok(ScannerCycleResult::new(cycle_status, dirty_usage_clear)
|
||||
.with_publication_epoch(publication_epoch)
|
||||
.with_remote_publication_lease_targets(remote_publication_lease_targets)
|
||||
.with_remote_dirty_usage_acknowledgements(remote_dirty_usage_acknowledgements)
|
||||
.with_failed_dirty_usage(!failed_buckets.is_empty())
|
||||
.with_pending_maintenance_work(pending_maintenance_work)
|
||||
|
||||
@@ -766,7 +766,7 @@ fn scanner_cycle_status_requires_a_clean_complete_snapshot() {
|
||||
DirtyUsageSnapshotStatus::Current,
|
||||
ScannerCycleActivityStatus::Unverified,
|
||||
),
|
||||
ScannerCycleStatus::Incomplete
|
||||
ScannerCycleStatus::Deferred(ScannerCycleDeferReason::ActivityBaselineUnavailable)
|
||||
);
|
||||
|
||||
for status in [
|
||||
@@ -815,6 +815,34 @@ fn scanner_cycle_status_requires_a_clean_complete_snapshot() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unverified_activity_defers_partial_and_floor_cycles() {
|
||||
let expected = ScannerCycleStatus::Deferred(ScannerCycleDeferReason::ActivityBaselineUnavailable);
|
||||
|
||||
assert_eq!(
|
||||
classify_nsscanner_cycle(
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
ScannerBucketScanStatus::Partial,
|
||||
DirtyUsageSnapshotStatus::Current,
|
||||
ScannerCycleActivityStatus::Unverified,
|
||||
),
|
||||
expected
|
||||
);
|
||||
assert_eq!(
|
||||
classify_nsscanner_cycle(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
ScannerBucketScanStatus::Complete,
|
||||
DirtyUsageSnapshotStatus::Current,
|
||||
ScannerCycleActivityStatus::Unverified,
|
||||
),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn structurally_complete_superseded_cycles_publish_without_claiming_convergence() {
|
||||
let (updates, mut receiver) = mpsc::channel(2);
|
||||
@@ -834,6 +862,15 @@ async fn structurally_complete_superseded_cycles_publish_without_claiming_conver
|
||||
.await
|
||||
.expect("incomplete snapshot suppression should succeed")
|
||||
);
|
||||
assert!(
|
||||
!publish_usage_snapshot(
|
||||
&updates,
|
||||
ScannerCycleStatus::Deferred(ScannerCycleDeferReason::ActivityBaselineUnavailable),
|
||||
DataUsageInfo::default(),
|
||||
)
|
||||
.await
|
||||
.expect("unverified activity suppression should succeed")
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
receiver
|
||||
@@ -855,11 +892,7 @@ async fn structurally_complete_superseded_cycles_publish_without_claiming_conver
|
||||
|
||||
#[test]
|
||||
fn scanner_cycle_fails_closed_for_namespace_disappearance() {
|
||||
for activity_status in [
|
||||
ScannerCycleActivityStatus::Changed,
|
||||
ScannerCycleActivityStatus::Unchanged,
|
||||
ScannerCycleActivityStatus::Unverified,
|
||||
] {
|
||||
for activity_status in [ScannerCycleActivityStatus::Changed, ScannerCycleActivityStatus::Unchanged] {
|
||||
assert_eq!(
|
||||
classify_nsscanner_cycle(
|
||||
false,
|
||||
@@ -872,6 +905,17 @@ fn scanner_cycle_fails_closed_for_namespace_disappearance() {
|
||||
ScannerCycleStatus::Incomplete
|
||||
);
|
||||
}
|
||||
assert_eq!(
|
||||
classify_nsscanner_cycle(
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
ScannerBucketScanStatus::NamespaceNotFound,
|
||||
DirtyUsageSnapshotStatus::Changed,
|
||||
ScannerCycleActivityStatus::Unverified,
|
||||
),
|
||||
ScannerCycleStatus::Deferred(ScannerCycleDeferReason::ActivityBaselineUnavailable)
|
||||
);
|
||||
assert_eq!(
|
||||
classify_nsscanner_cycle(
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user