Jackie-Jiang opened a new pull request, #19855:
URL: https://github.com/apache/pinot/pull/19855

   ## Summary
   
   `MultiClusterIntegrationTest` and `SameTableNameMultiClusterIntegrationTest` 
fail in `setUp` with `RuntimeException: Failed to start http server`, caused by 
`BindException: Address already in use`. This is the most common Integration 
Test Set 2 failure: 25 of the 43 failed jobs between 2026-09-26 and 2026-10-13, 
all at the same line (`BaseMultiClusterIntegrationTest.java:148`).
   
   ### Root cause
   `startBrokerWithUnavailableCluster` probed its HTTP port with 
`findOpenPort(55000)`, which only checks that the port is free and then 
releases it. The broker binds that port only at the end of `start()`, after its 
connection to the deliberately unreachable ZK at `localhost:29999` times out, 
about 60 seconds later. 55000 is inside the Linux ephemeral range 
(32768–60999), and it is even, which is the parity `connect()` tries first. The 
two CI lanes share one runner, so an outgoing connection can take the port 
during that window.
   
   The other hard-coded ports either sit below the ephemeral range 
(30000–32002) or are bound within about a second of the probe (40000–42002), 
which is why only this broker failed.
   
   ### Fix
   - All ports come from the per-fork `ControllerTest` port range 
(`_nextControllerPort`, `_nextBrokerPort`, `_nextServerPort`) instead of 
hard-coded 30000 / 40000 / 55000 bases. CI sets that range per lane via 
`pinot.test.port.base`, to disjoint bands below the ephemeral range.
   - Brokers and servers get explicit multi-stage engine ports from the same 
range. Otherwise they fall back to `NetUtils.findOpenPort()` (a bind to port 
0), and the broker's query runner port would hit the same 60-second window.
   - `tearDown` runs with `alwaysRun = true`, so a failed `setUp` no longer 
leaves both clusters running for the rest of the lane. Each component is 
stopped independently, so a half-started one doesn't prevent the rest from 
stopping.
   
   ### Cleanup
   - `ClusterConfig` is replaced by a cluster name on `ClusterComponents`, so a 
broker reads its remote cluster's name from the remote `ClusterComponents`.
   - Both broker setups share one `initBroker` helper. 
`_brokerWithUnavailableCluster` is a plain `BaseBrokerStarter`, and broker 
ports are read through `getPort()`.
   - The touched files were also reformatted, so the diff is larger than the 
logic change.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


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