chengxilo opened a new issue, #3890: URL: https://github.com/apache/iggy/issues/3890
### Bug description ## Summary A server whose TCP listener binds a wildcard reports that wildcard as its own client-facing address in `GetClusterMetadata`. The Go SDK collects roster addresses into its reconnect candidate ring, so `0.0.0.0:8090` becomes a dial target. ## Reproduction The shipped BDD compose file already reproduces it. In `bdd/docker-compose.server.yml`. https://github.com/apache/iggy/blob/7c0fd68421aa610897fdbc7331f1cb22848fb386/bdd/docker-compose.server.yml#L32 https://github.com/apache/iggy/blob/7c0fd68421aa610897fdbc7331f1cb22848fb386/bdd/docker-compose.server.yml#L67 Confirmed directly by varying only the bind address on one binary: | Bind | Client dialed | Reported IP | | ---- | ------------- | ----------- | | `127.0.0.1:8090` | `127.0.0.1:8090` | `127.0.0.1` (usable) | | `0.0.0.0:8190` | `127.0.0.1:8190` | `0.0.0.0` (not usable) | With the cluster disabled, `ClusterRoster::cluster_metadata` reports `self_ip`, which is assigned the bind address verbatim: ```rust // core/server/src/bootstrap.rs:1719 self_ip: topology.client_listen_addr.ip().to_string(), ``` ## What the Go SDK does with it 1. Every sign-in runs leader settlement: `settleOnLeader` (`foreign/go/client/tcp/tcp_session_management.go:69`). 2. `clusterAddresses` (`foreign/go/internal/util/leader_aware.go:126`) collects an address for every healthy node, unconditionally. 3. Those land in `knownServerAddresses` (`foreign/go/client/tcp/tcp_session_management.go:212`). 4. `connectionCandidates` (`foreign/go/client/tcp/tcp_core.go:998`) appends them to the configured addresses, and `Connect` rotates through the result on every retry (`tcp_core.go:924`). Result for the reproduction above: `["iggy-server:8090", "0.0.0.0:8090"]`. ## Root cause The advertised-address mechanism already exists and is complete for roster nodes: `ClusterNodeConfig.advertised_address` plus the client-CIDR-scoped `advertised_addresses` selectors (`core/configs/src/server_config/cluster.rs:369-377`), with strict boot validation (`cluster.rs:978-1042`) and cross-node endpoint conflict detection (`cluster.rs:1357`). `self_metadata()` (`cluster_meta.rs:134`) does not participate in any of it. It is a parallel path that substitutes the bind address, manufacturing an addressthe server does not actually know. ## Proposed fix Publish only dialable address A concrete bind IP is an interface the operator named, so it is reported as-is and that path is unchanged. An unspecified one carries no client-facing information, so the node publishes no address at all. Nothing is invented to fill the gap. The self node is the one node whose address a client never needs told: it is already connected to it, and with a single-node roster there is nowhere to fail over to. Empty is already a value the wire carries, via `ClusterRoster::disabled()` (`cluster_meta.rs:80`), so no protocol change is involved. ### Affected area / component _No response_ ### Deployment None ### Versions _No response_ ### Hardware / environment _No response_ ### Sample code _No response_ ### Logs _No response_ ### Iggy server config _No response_ ### Reproduction _No response_ ### Contribution - [ ] I'm willing to submit a pull request to fix this bug ### Good first issue - [ ] I think this could be a good first issue for a new contributor -- 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]
