Copilot commented on code in PR #3488:
URL: https://github.com/apache/dubbo-go/pull/3488#discussion_r3577998750


##########
common/url.go:
##########
@@ -50,7 +50,6 @@ const (
        CONFIGURATOR
        ROUTER
        PROVIDER

Review Comment:
   Removing the exported `PROTOCOL` constant is a breaking change for 
downstream users that referenced `common.PROTOCOL` as the canonical key for 
protocol in URL maps/params. Since this PR is primarily a perf refactor, 
consider keeping `PROTOCOL` as a deprecated alias to `constant.ProtocolKey` to 
preserve compatibility.



##########
common/url.go:
##########
@@ -1163,26 +1195,91 @@ func IsEquals(left *URL, right *URL, excludes 
...string) bool {
                return false
        }
 
-       leftMap := left.ToMap()
-       rightMap := right.ToMap()
-       for _, exclude := range excludes {
-               delete(leftMap, exclude)
-               delete(rightMap, exclude)
+       excluded := newKeySet(excludes)
+       return equalScalars(left, right, excluded) &&
+               equalLocation(left.Location, right.Location, excluded) &&
+               equalParams(left, right, excluded)
+}
+
+// equalScalars compares the non-param scalar fields of two URLs, skipping any 
excluded key.
+func equalScalars(left, right *URL, excluded keySet) bool {
+       scalars := []struct {
+               key         string
+               left, right string
+       }{
+               {constant.ProtocolKey, left.Protocol, right.Protocol},
+               {constant.UsernameKey, left.Username, right.Username},
+               {constant.PasswordKey, left.Password, right.Password},
+               {constant.PathKey, left.Path, right.Path},
        }
+       for _, s := range scalars {
+               if s.left != s.right && !excluded.contains(s.key) {
+                       return false
+               }
+       }
+       return true
+}
 
-       if len(leftMap) != len(rightMap) {
+// equalLocation compares two "host:port" locations, skipping host and/or port 
when excluded.
+func equalLocation(left, right string, excluded keySet) bool {
+       if left == right {
+               return true
+       }
+
+       hostExcluded := excluded.contains(constant.HostKey)
+       portExcluded := excluded.contains(constant.PortKey)
+       if hostExcluded && portExcluded {
+               return true
+       }
+
+       leftHost, leftPort := parseLocation(left)
+       rightHost, rightPort := parseLocation(right)
+       if !hostExcluded && leftHost != rightHost {
+               return false
+       }
+       if !portExcluded && leftPort != rightPort {
                return false
        }
+       return true
+}
 
-       for lk, lv := range leftMap {
-               if rv, ok := rightMap[lk]; !ok {
-                       return false
-               } else if lv != rv {
+// equalParams compares the params of two URLs, skipping excluded keys. It 
avoids
+// materializing both maps by snapshotting only the left side and streaming 
the right.
+func equalParams(left, right *URL, excluded keySet) bool {
+       leftParams := make(map[string]string)
+       left.RangeParams(func(key, value string) bool {
+               if !excluded.contains(key) {
+                       leftParams[key] = value
+               }
+               return true
+       })
+
+       rightCount := 0
+       matched := true
+       right.RangeParams(func(key, value string) bool {
+               if excluded.contains(key) {
+                       return true
+               }
+               rightCount++
+               if lv, ok := leftParams[key]; !ok || lv != value {
+                       matched = false
                        return false
                }
-       }
+               return true
+       })
 
-       return true
+       return matched && rightCount == len(leftParams)
+}
+
+// parseLocation splits "host:port" into host and port
+func parseLocation(location string) (host, port string) {
+       if location == "" {
+               return "", "0"
+       }
+       if idx := strings.IndexByte(location, ':'); idx >= 0 {
+               return location[:idx], location[idx+1:]
+       }
+       return location, "0"
 }

Review Comment:
   `parseLocation` currently returns everything after the first ':' as the 
port. This changes `ToMap()["port"]` and `IsEquals` semantics for locations 
that contain additional ':' (e.g., registry address lists like 
"127.0.0.1:2181,127.0.0.1:2182"), where the previous behavior only took the 
substring between the first and second ':' (matching `strings.Split(location, 
":")[1]`). This violates the stated goal of preserving existing host/port 
behavior.



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to