mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-31 17:28:12 +00:00
fix(internode): guard msgpack-only JSON fallback (#5180)
Keep internode JSON compatibility fields unless operators explicitly confirm fleet-wide msgpack-only readiness. This prevents a single legacy rollout flag from emptying JSON fields in mixed-version clusters where older peers may still read the legacy JSON payload. Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -1022,9 +1022,8 @@ fn encode_msgpack<T: Serialize>(value: &T) -> Result<Vec<u8>> {
|
||||
}
|
||||
|
||||
/// JSON compatibility string for a dual-encoded (`_bin` + text) request field. Returns an empty
|
||||
/// string when msgpack-only mode is enabled (grpc-optimization P2-1) so the redundant JSON copy is
|
||||
/// not sent; otherwise the legacy JSON encoding. Only use for fields whose peer decodes `_bin`
|
||||
/// first — the paired `_bin` (msgpack) field must always be sent alongside.
|
||||
/// string only when msgpack-only mode and its explicit fleet confirmation guard are both enabled;
|
||||
/// otherwise the legacy JSON encoding is retained for old peers.
|
||||
fn compat_json<T: Serialize>(value: &T) -> Result<String> {
|
||||
if rustfs_protos::internode_rpc_msgpack_only() {
|
||||
return Ok(String::new());
|
||||
@@ -3019,15 +3018,45 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn compat_json_dual_writes_by_default() {
|
||||
// msgpack-only defaults off, so compat_json returns the JSON encoding (dual-write). The
|
||||
// empty-string (msgpack-only) path is exercised via the env flag in integration, not here,
|
||||
// to keep this test independent of process-global env state.
|
||||
let resp = sample_read_multiple_resp("file", b"data");
|
||||
let json = compat_json(&resp).expect("compat_json should encode");
|
||||
assert!(!json.is_empty());
|
||||
assert_eq!(json, serde_json::to_string(&resp).expect("json should encode"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compat_json_keeps_json_when_msgpack_only_lacks_fleet_confirmation() {
|
||||
temp_env::with_vars(
|
||||
[
|
||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, None::<&str>),
|
||||
],
|
||||
|| {
|
||||
let resp = sample_read_multiple_resp("file", b"data");
|
||||
let json = compat_json(&resp).expect("compat_json should encode");
|
||||
|
||||
assert!(!json.is_empty(), "old JSON peers must remain compatible without fleet confirmation");
|
||||
assert_eq!(json, serde_json::to_string(&resp).expect("json should encode"));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compat_json_omits_json_only_after_fleet_confirmation() {
|
||||
temp_env::with_vars(
|
||||
[
|
||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY, Some("true")),
|
||||
(rustfs_config::ENV_INTERNODE_RPC_MSGPACK_ONLY_FLEET_CONFIRMED, Some("true")),
|
||||
],
|
||||
|| {
|
||||
let resp = sample_read_multiple_resp("file", b"data");
|
||||
let json = compat_json(&resp).expect("compat_json should encode");
|
||||
|
||||
assert!(json.is_empty(), "msgpack-only may empty JSON only after explicit fleet confirmation");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_multiple_response_decode_reports_corrupt_msgpack_item() {
|
||||
let endpoint = sample_remote_endpoint();
|
||||
|
||||
Reference in New Issue
Block a user