Copilot commented on code in PR #307:
URL: https://github.com/apache/fluss-rust/pull/307#discussion_r2802913067


##########
crates/fluss/src/client/metadata.rs:
##########
@@ -273,4 +281,18 @@ mod tests {
         let cluster = metadata.get_cluster();
         assert!(cluster.get_tablet_server(1).is_none());
     }
+
+    #[test]
+    fn parse_bootstrap_variants() {
+        // valid IP
+        let addr = Metadata::parse_bootstrap("127.0.0.1:8080").unwrap();
+        assert_eq!(addr.port(), 8080);
+
+        // valid hostname
+        let addr = Metadata::parse_bootstrap("localhost:9090").unwrap();
+        assert_eq!(addr.port(), 9090);
+
+        // invalid input

Review Comment:
   The test case "invalid_address" verifies that an invalid address returns an 
error, but it would be more robust to also check for specific edge cases like: 
addresses without ports (e.g., "localhost"), addresses with invalid ports 
(e.g., "localhost:99999"), IPv6 addresses (e.g., "[::1]:8080"), and empty 
strings. These cases would ensure the function handles malformed input 
correctly.
   ```suggestion
           // valid IPv6 address
           let addr = Metadata::parse_bootstrap("[::1]:8080").unwrap();
           assert_eq!(addr.port(), 8080);
   
           // invalid input: missing port
           assert!(Metadata::parse_bootstrap("localhost").is_err());
   
           // invalid input: out-of-range port
           assert!(Metadata::parse_bootstrap("localhost:99999").is_err());
   
           // invalid input: empty string
           assert!(Metadata::parse_bootstrap("").is_err());
   
           // invalid input: nonsensical address
   ```



##########
crates/fluss/src/client/metadata.rs:
##########
@@ -44,13 +44,21 @@ impl Metadata {
         })
     }
 
+    fn parse_bootstrap(boot_strap: &str) -> Result<SocketAddr> {
+        let addr = boot_strap
+            .to_socket_addrs()
+            .map_err(|e| Error::IllegalArgument {
+                message: format!("Invalid bootstrap address '{boot_strap}': 
{e}"),
+            })?
+            .next()
+            .ok_or_else(|| Error::IllegalArgument {
+                message: format!("Unable to resolve bootstrap address 
'{boot_strap}'"),
+            })?;
+        Ok(addr)
+    }

Review Comment:
   The method uses `to_socket_addrs()` which performs DNS resolution 
synchronously, blocking the current thread. Since this method is called from 
`init_cluster` (an async function), this DNS lookup could block the executor 
thread, which is problematic in async contexts. Consider using async DNS 
resolution instead, such as `tokio::net::lookup_host()`, to avoid blocking the 
async runtime.



##########
crates/fluss/src/client/metadata.rs:
##########
@@ -44,13 +44,21 @@ impl Metadata {
         })
     }
 
+    fn parse_bootstrap(boot_strap: &str) -> Result<SocketAddr> {
+        let addr = boot_strap
+            .to_socket_addrs()
+            .map_err(|e| Error::IllegalArgument {
+                message: format!("Invalid bootstrap address '{boot_strap}': 
{e}"),
+            })?
+            .next()
+            .ok_or_else(|| Error::IllegalArgument {
+                message: format!("Unable to resolve bootstrap address 
'{boot_strap}'"),
+            })?;

Review Comment:
   When `to_socket_addrs()` resolves a hostname to multiple IP addresses, using 
`.next()` arbitrarily selects the first resolved address. This could lead to 
inconsistent behavior across DNS resolutions and doesn't provide predictable 
IPv4 vs IPv6 preference. Consider documenting this behavior or implementing a 
more deterministic selection strategy (e.g., preferring IPv4 or allowing 
configuration of address family preference).
   ```suggestion
           // Resolve all socket addresses and deterministically choose one.
           let mut addrs = boot_strap.to_socket_addrs().map_err(|e| 
Error::IllegalArgument {
               message: format!("Invalid bootstrap address '{boot_strap}': 
{e}"),
           })?;
   
           // Prefer IPv4 addresses; if none are available, fall back to the 
first IPv6.
           let mut ipv6_candidate: Option<SocketAddr> = None;
           while let Some(addr) = addrs.next() {
               if addr.is_ipv4() {
                   return Ok(addr);
               }
               if ipv6_candidate.is_none() {
                   ipv6_candidate = Some(addr);
               }
           }
   
           let addr = ipv6_candidate.ok_or_else(|| Error::IllegalArgument {
               message: format!("Unable to resolve bootstrap address 
'{boot_strap}'"),
           })?;
   ```



##########
crates/fluss/src/client/metadata.rs:
##########
@@ -44,13 +44,21 @@ impl Metadata {
         })
     }
 
+    fn parse_bootstrap(boot_strap: &str) -> Result<SocketAddr> {

Review Comment:
   The parameter name uses an underscore ("boot_strap") instead of the standard 
compound word "bootstrap" used elsewhere in the codebase (see field name at 
line 34, method parameter at line 38). This inconsistency makes the naming 
confusing. The parameter should be renamed to "bootstrap" for consistency.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to