Report actual listener addresses after binding
What is the problem your feature solves, or the need it fulfills?
Pingora accepts port 0 in a listening-service configuration, but callers cannot learn the assigned port after moving the service into Server.
A full-server test must therefore use a fixed port or reserve one with a temporary socket. Fixed ports collide when tests run concurrently; closing the temporary socket before Pingora starts leaves a race in which another process can claim the port.
Describe the solution you'd like
Expose the addresses of a listening service after Pingora binds them:
let mut bound_addresses = service.watch_bound_addresses();
server.add_service(service);
let addresses = bound_addresses.wait_for(Option::is_some).await?;
The draft uses a watch channel. Its value changes from None to the bound TCP or Unix-domain addresses after all listeners bind, before accept loops start and before dependent services are notified that the service is ready. The channel closes without a value if listener startup fails. A callback or one-shot receiver would also satisfy the use case.
Describe alternatives you've considered
- Accept a pre-bound listener. This gives the caller the address, but moves fd ownership outside Pingora and complicates graceful transfer.
- Reserve a port with a temporary socket, close it, and ask Pingora to bind the same port (race-y semantics, seems bad)
- Expose addresses from
Listeners::build. The built listeners already know their addresses, but normal applications do not call this method; listening services call it insideServerstartup.
Additional context
I have a draft (report-bound-listeners) that I'll open as a PR.
Source: cloudflare/pingora