fix(filemeta): key round-tripped replication reset state by canonical header (backlog#799 B16) (#4325)

fix(filemeta): key round-tripped replication reset state by canonical header (backlog#799 B19->B16)

`get_internal_replication_state` stored the reset status under the bare ARN after
stripping the internal prefix, while the write and lookup sides
(`get_replication_state` / `ReplicationState::target_state`) use the full
`target_reset_header(arn)` key. A `target_state` fallback masked the lookup miss,
but the map stayed keyed inconsistently (bare on read, full on write), which can
drop reset state across merge/reflatten cycles.

Store the canonical `target_reset_header(arn)` key on read so the map is
consistent everywhere; the lookup fallback becomes belt-and-suspenders rather
than load-bearing. Adds a round-trip regression test.

Refs backlog#799 (B16), tracked in rustfs/backlog#863.
This commit is contained in:
Zhengchao An
2026-07-06 22:58:52 +08:00
committed by GitHub
parent 31c6859965
commit 92596da7fa
+33 -1
View File
@@ -2326,7 +2326,14 @@ fn get_internal_replication_state(metadata: &HashMap<String, String>) -> Option<
_ => {
if let Some(arn) = sub_key.strip_prefix("replication-reset-") {
has = true;
rs.reset_statuses_map.insert(arn.to_string(), v.clone());
// Store the canonical full-header key so the map matches
// the key `target_reset_header()` produces on the
// write/lookup side. Storing the bare ARN keyed the map
// inconsistently (bare on read, full on write), which
// could drop reset state across merge/reflatten cycles
// (backlog#799 B16).
rs.reset_statuses_map
.insert(crate::replication::target_reset_header(arn), v.clone());
}
}
}
@@ -3645,4 +3652,29 @@ mod tests {
assert_eq!(dm.version_id, Some(vid));
assert!(dm.mod_time.is_some());
}
#[test]
fn get_internal_replication_state_keeps_canonical_reset_key() {
// The reset status is stored on disk under the full internal key; parsing
// must keep it keyed by `target_reset_header(arn)` (not the bare ARN) so
// `ReplicationState::target_state` finds it after a round trip
// (backlog#799 B16).
let arn = "arn:rustfs:replication:us-east-1:target:bucket";
let ts = "2026-06-30T00:00:00Z;reset-1".to_string();
let key = crate::replication::target_reset_header(arn);
let mut metadata = HashMap::new();
metadata.insert(key.clone(), ts.clone());
let rs = get_internal_replication_state(&metadata).expect("reset state should parse");
assert_eq!(
rs.reset_statuses_map.get(&key),
Some(&ts),
"map must be keyed by target_reset_header, not the bare ARN"
);
assert_eq!(
rs.target_state(arn).resync_timestamp,
ts,
"lookup must find the round-tripped reset status"
);
}
}