mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-21 03:46:37 +00:00
fix(sts): return Query API-compatible responses (#5282)
* fix(sts): return Query API-compatible responses * fix(sts): resolve review and CI failures * fix(sts): harden query response conversion * test(e2e): stabilize transition conflict coverage * fix(ilm): retry vanished transition admission CAS * test(e2e): narrow transition overlap coverage --------- Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -9483,6 +9483,48 @@ mod tests {
|
||||
assert_eq!(current.lease_id, second.lease_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn manual_transition_scope_missing_current_is_retryable_cas_miss() {
|
||||
let (_paths, ecstore) = setup_test_env().await;
|
||||
let options = ManualTransitionRunOptions {
|
||||
prefix: "logs/".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let first = ManualTransitionJobRecord::new(Uuid::new_v4(), "manual-replace-race-bucket", &options, "first-owner");
|
||||
save_manual_transition_scope_admission_if_absent(ecstore.clone(), &ManualTransitionScopeAdmission::from_job(&first))
|
||||
.await
|
||||
.expect("first scope admission should save");
|
||||
let (_loaded, etag) = load_manual_transition_scope_admission_with_etag(ecstore.clone(), &first.scope_key)
|
||||
.await
|
||||
.expect("first scope admission should load with an ETag");
|
||||
let object = manual_transition_scope_record_object_name(&first.scope_key).expect("scope admission path should encode");
|
||||
config_boundary::delete_config(ecstore.clone(), &object)
|
||||
.await
|
||||
.expect("current scope admission should be deleted");
|
||||
|
||||
let replacement =
|
||||
ManualTransitionJobRecord::new(Uuid::new_v4(), "manual-replace-race-bucket", &options, "replacement-owner");
|
||||
let stale_replace = save_manual_transition_scope_admission_if_current(
|
||||
ecstore.clone(),
|
||||
&ManualTransitionScopeAdmission::from_job(&replacement),
|
||||
&etag,
|
||||
)
|
||||
.await
|
||||
.expect_err("replacing a disappeared scope admission must report a CAS miss");
|
||||
assert_eq!(stale_replace, Error::PreconditionFailed);
|
||||
|
||||
let claim =
|
||||
claim_manual_transition_scope_admission(ecstore.clone(), &ManualTransitionScopeAdmission::from_job(&replacement))
|
||||
.await
|
||||
.expect("replacement claim should recover through the create path");
|
||||
assert_eq!(claim, ManualTransitionScopeAdmissionClaim::Claimed);
|
||||
let current = load_manual_transition_scope_admission(ecstore, &replacement.scope_key)
|
||||
.await
|
||||
.expect("replacement scope admission should be saved");
|
||||
assert_eq!(current.job_id, replacement.job_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn manual_transition_admission_reclaims_stale_scope_records() {
|
||||
|
||||
@@ -1466,7 +1466,7 @@ pub async fn save_manual_transition_scope_admission_if_current(
|
||||
admission.validate().map_err(manual_transition_job_store_error)?;
|
||||
let object = manual_transition_scope_record_object_name(&admission.scope_key).map_err(manual_transition_job_store_error)?;
|
||||
let data = serde_json::to_vec(admission).map_err(Error::other)?;
|
||||
config_boundary::save_config_with_opts(
|
||||
match config_boundary::save_config_with_opts(
|
||||
api,
|
||||
&object,
|
||||
data,
|
||||
@@ -1480,6 +1480,12 @@ pub async fn save_manual_transition_scope_admission_if_current(
|
||||
},
|
||||
)
|
||||
.await
|
||||
{
|
||||
Err(Error::ObjectNotFound(bucket, current_object)) if bucket == RUSTFS_META_BUCKET && current_object == object => {
|
||||
Err(Error::PreconditionFailed)
|
||||
}
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn claim_manual_transition_scope_admission(
|
||||
|
||||
Reference in New Issue
Block a user