fix(seaweed-volume): parse host:port.grpcPort in master address (#9235)

The Go ServerAddress format encodes an optional explicit gRPC port as
host:port.grpcPort. The Rust heartbeat client only handled host:port
(falling back to port+10000), so feeding it host:port.grpcPort yielded
a malformed gRPC target like "host:port.grpcPort", which manifests as
checkWithMaster transport errors.

Mirror pb.ServerToGrpcAddress(): if the part after the last ':' contains
a '.' followed by a valid u16, treat that suffix as the explicit gRPC
port; otherwise keep the +10000 default.

Refs #9234.
This commit is contained in:
Chris Lu
2026-04-27 01:44:11 -07:00
committed by GitHub
parent a2639b533e
commit 045ace29d5

View File

@@ -169,10 +169,20 @@ pub async fn run_heartbeat_with_state(
}
}
/// Convert a master address "host:port" to a gRPC host:port target.
/// The Go master uses port + 10000 for gRPC by default.
/// Convert a master address to a gRPC `host:port` target.
///
/// Mirrors Go's `pb.ServerToGrpcAddress()`:
/// - `host:port.grpcPort` returns `host:grpcPort` (explicit gRPC port).
/// - `host:port` returns `host:(port+10000)` (Go's default offset).
/// - Anything that fails to parse is returned unchanged.
pub fn to_grpc_address(master_addr: &str) -> String {
if let Some((host, port_str)) = master_addr.rsplit_once(':') {
// "host:port.grpcPort" — the part after the last '.' is the gRPC port.
if let Some((_, grpc_port)) = port_str.rsplit_once('.') {
if grpc_port.parse::<u16>().is_ok() {
return format!("{}:{}", host, grpc_port);
}
}
if let Ok(port) = port_str.parse::<u16>() {
let grpc_port = port + 10000;
return format!("{}:{}", host, grpc_port);
@@ -1038,6 +1048,26 @@ mod tests {
})
}
#[test]
fn test_to_grpc_address_default_offset() {
assert_eq!(to_grpc_address("10.0.0.1:9333"), "10.0.0.1:19333");
assert_eq!(to_grpc_address("localhost:9333"), "localhost:19333");
}
#[test]
fn test_to_grpc_address_explicit_grpc_port() {
// host:port.grpcPort form — gRPC port is what's after the dot.
assert_eq!(to_grpc_address("10.85.183.6:5300.6300"), "10.85.183.6:6300");
assert_eq!(to_grpc_address("master.local:9333.19333"), "master.local:19333");
}
#[test]
fn test_to_grpc_address_returns_input_when_unparseable() {
assert_eq!(to_grpc_address(""), "");
assert_eq!(to_grpc_address("no-port"), "no-port");
assert_eq!(to_grpc_address("host:not-a-port"), "host:not-a-port");
}
#[test]
fn test_build_heartbeat_includes_store_identity_and_disk_metadata() {
let temp_dir = tempfile::tempdir().unwrap();