Candidate cleanup owed is one method both abort intents share
The two-flag helper let either call site swap or fold an argument unnoticed. DeploymentTransaction::candidate_cleanup_owed reads the transaction itself, and a four-row table drives the method and both intents. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
94c7691cb6
commit
5f8417589d
1 changed files with 45 additions and 32 deletions
|
|
@ -1370,6 +1370,17 @@ impl DeploymentTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether an abort owes the candidate's durable cleanup: it does once an
|
||||
/// activation was issued or a workload was observed, either of which leaves
|
||||
/// something behind.
|
||||
fn candidate_cleanup_owed(&self) -> CleanupEvidence {
|
||||
if self.activation.is_some() || self.workload.is_some() {
|
||||
CleanupEvidence::Pending
|
||||
} else {
|
||||
CleanupEvidence::Skipped
|
||||
}
|
||||
}
|
||||
|
||||
fn rejected(command: &DeploymentCommand, error: anyhow::Error, now: u64) -> Result<Self> {
|
||||
let mut transaction = Self::new(command, command.selector.clone(), 0, None, now)?;
|
||||
let detail = truncate(&format!("{error:#}"), 2048);
|
||||
|
|
@ -7991,10 +8002,7 @@ fn incumbent_was_stopped_during_fencing(fencing: &FencingEvidence) -> bool {
|
|||
fn pre_fencing_abort_intent(transaction: &DeploymentTransaction, error: &str) -> PreFencingAbort {
|
||||
PreFencingAbort {
|
||||
error: truncate(error, 2048),
|
||||
candidate_cleanup: candidate_cleanup_requirement(
|
||||
transaction.activation.is_some(),
|
||||
transaction.workload.is_some(),
|
||||
),
|
||||
candidate_cleanup: transaction.candidate_cleanup_owed(),
|
||||
topology_reconciliation: transaction.abort_topology_reconciliation(),
|
||||
source_cleanup: if transaction.command_kind == CommandKind::Deploy {
|
||||
CleanupEvidence::Pending
|
||||
|
|
@ -8025,10 +8033,7 @@ fn post_fencing_abort_intent(
|
|||
} else {
|
||||
CleanupEvidence::Skipped
|
||||
},
|
||||
candidate_cleanup: candidate_cleanup_requirement(
|
||||
transaction.activation.is_some(),
|
||||
transaction.workload.is_some(),
|
||||
),
|
||||
candidate_cleanup: transaction.candidate_cleanup_owed(),
|
||||
topology_reconciliation: transaction.abort_topology_reconciliation(),
|
||||
source_cleanup: if transaction.command_kind == CommandKind::Deploy {
|
||||
CleanupEvidence::Pending
|
||||
|
|
@ -8038,17 +8043,6 @@ fn post_fencing_abort_intent(
|
|||
}
|
||||
}
|
||||
|
||||
fn candidate_cleanup_requirement(
|
||||
has_prepared_activation: bool,
|
||||
has_workload_observation: bool,
|
||||
) -> CleanupEvidence {
|
||||
if has_prepared_activation || has_workload_observation {
|
||||
CleanupEvidence::Pending
|
||||
} else {
|
||||
CleanupEvidence::Skipped
|
||||
}
|
||||
}
|
||||
|
||||
fn sequence_requires_admission(
|
||||
latest: Option<&TopologyEvidence>,
|
||||
maximum_admitted_sequence: u64,
|
||||
|
|
@ -9803,19 +9797,38 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn activation_without_workload_still_requires_durable_candidate_cleanup() {
|
||||
assert_eq!(
|
||||
candidate_cleanup_requirement(true, false),
|
||||
CleanupEvidence::Pending
|
||||
);
|
||||
assert_eq!(
|
||||
candidate_cleanup_requirement(true, true),
|
||||
CleanupEvidence::Pending
|
||||
);
|
||||
assert_eq!(
|
||||
candidate_cleanup_requirement(false, false),
|
||||
CleanupEvidence::Skipped
|
||||
);
|
||||
fn candidate_cleanup_is_owed_when_an_activation_or_a_workload_exists() -> Result<()> {
|
||||
// (activation issued, workload observed, expected cleanup)
|
||||
let rows = [
|
||||
(false, false, CleanupEvidence::Skipped),
|
||||
(true, false, CleanupEvidence::Pending),
|
||||
(false, true, CleanupEvidence::Pending),
|
||||
(true, true, CleanupEvidence::Pending),
|
||||
];
|
||||
for (has_activation, has_workload, expected) in rows {
|
||||
let world = ContinuityProjection::after_candidate_observed()?;
|
||||
let mut transaction = world.continuity_transaction()?;
|
||||
if !has_activation {
|
||||
transaction.activation = None;
|
||||
}
|
||||
transaction.workload = has_workload.then(|| workload(1000, 1, 2));
|
||||
assert_eq!(
|
||||
transaction.candidate_cleanup_owed(),
|
||||
expected,
|
||||
"activation {has_activation}, workload {has_workload}"
|
||||
);
|
||||
assert_eq!(
|
||||
pre_fencing_abort_intent(&transaction, "x").candidate_cleanup,
|
||||
expected,
|
||||
"pre-fencing intent, activation {has_activation}, workload {has_workload}"
|
||||
);
|
||||
assert_eq!(
|
||||
post_fencing_abort_intent(&transaction, "x").candidate_cleanup,
|
||||
expected,
|
||||
"post-fencing intent, activation {has_activation}, workload {has_workload}"
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Reference in a new issue