mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-02 02:08:41 +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:
@@ -239,6 +239,13 @@ fn classify_nsscanner_cycle(
|
||||
dirty_usage_status: DirtyUsageSnapshotStatus,
|
||||
activity_status: ScannerCycleActivityStatus,
|
||||
) -> ScannerCycleStatus {
|
||||
// The post-scan activity proof is required regardless of why the scan was
|
||||
// incomplete. Returning Incomplete first would apply the long ordinary
|
||||
// retry/backoff path to an unverifiable publication and could acknowledge
|
||||
// a cycle without a movement-generation proof.
|
||||
if activity_status == ScannerCycleActivityStatus::Unverified {
|
||||
return ScannerCycleStatus::Deferred(ScannerCycleDeferReason::ActivityBaselineUnavailable);
|
||||
}
|
||||
if budget_elapsed
|
||||
|| cancelled
|
||||
|| !matches!(bucket_scan_status, ScannerBucketScanStatus::Complete)
|
||||
@@ -252,7 +259,6 @@ fn classify_nsscanner_cycle(
|
||||
|
||||
match (activity_status, dirty_usage_status) {
|
||||
(ScannerCycleActivityStatus::Unchanged, DirtyUsageSnapshotStatus::Current) => ScannerCycleStatus::Complete,
|
||||
(ScannerCycleActivityStatus::Unverified, _) => ScannerCycleStatus::Incomplete,
|
||||
_ => ScannerCycleStatus::Superseded,
|
||||
}
|
||||
}
|
||||
@@ -307,10 +313,16 @@ async fn scanner_cycle_activity_status(
|
||||
store: &ECStore,
|
||||
distributed: bool,
|
||||
before: &crate::scanner::ScannerActivitySnapshot,
|
||||
) -> ScannerCycleActivityStatus {
|
||||
) -> (ScannerCycleActivityStatus, Vec<(String, String, u64)>) {
|
||||
match crate::scanner::probe_scanner_activity(store, distributed).await {
|
||||
Ok(after) if after == *before => ScannerCycleActivityStatus::Unchanged,
|
||||
Ok(_) => ScannerCycleActivityStatus::Changed,
|
||||
Ok(after) => {
|
||||
let status = if after == *before {
|
||||
ScannerCycleActivityStatus::Unchanged
|
||||
} else {
|
||||
ScannerCycleActivityStatus::Changed
|
||||
};
|
||||
(status, crate::scanner::scanner_activity_publication_lease_targets(&after))
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
target: "rustfs::scanner::io",
|
||||
@@ -321,7 +333,7 @@ async fn scanner_cycle_activity_status(
|
||||
error = %err,
|
||||
"Scanner cycle activity verification failed"
|
||||
);
|
||||
ScannerCycleActivityStatus::Unverified
|
||||
(ScannerCycleActivityStatus::Unverified, Vec::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,6 +611,7 @@ pub(crate) struct ScannerCycleResult {
|
||||
publication_epoch: Option<u64>,
|
||||
dirty_usage_clear: Option<DirtyUsageBuckets>,
|
||||
remote_dirty_usage_acknowledgements: Vec<crate::scanner::ScannerDirtyUsageAcknowledgement>,
|
||||
remote_publication_lease_targets: Vec<(String, String, u64)>,
|
||||
failed_dirty_usage: bool,
|
||||
pending_maintenance_work: bool,
|
||||
required_cycle_floor: Option<u64>,
|
||||
@@ -611,6 +624,7 @@ impl ScannerCycleResult {
|
||||
publication_epoch: None,
|
||||
dirty_usage_clear,
|
||||
remote_dirty_usage_acknowledgements: Vec::new(),
|
||||
remote_publication_lease_targets: Vec::new(),
|
||||
failed_dirty_usage: false,
|
||||
pending_maintenance_work: false,
|
||||
required_cycle_floor: None,
|
||||
@@ -649,6 +663,15 @@ impl ScannerCycleResult {
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn with_remote_publication_lease_targets(mut self, targets: Vec<(String, String, u64)>) -> Self {
|
||||
self.remote_publication_lease_targets = targets;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn remote_publication_lease_targets(&self) -> &[(String, String, u64)] {
|
||||
&self.remote_publication_lease_targets
|
||||
}
|
||||
|
||||
pub(crate) fn acknowledge_durable_usage(self) -> Vec<crate::scanner::ScannerDirtyUsageAcknowledgement> {
|
||||
if let Some(snapshot) = self.dirty_usage_clear {
|
||||
clear_dirty_usage_buckets(&snapshot);
|
||||
|
||||
Reference in New Issue
Block a user