Skip to content

fix: answer conductor socket address queries asynchronously (#3693) - #3707

Merged
He-Pin merged 1 commit into
mainfrom
fix-3693-controller-async-sockaddr
Oct 26, 2026
Merged

He-Pin merged 1 commit into
mainfrom
fix-3693-controller-async-sockaddr

Conversation

@He-Pin

@He-Pin He-Pin commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Motivation

The test conductor answered address queries by blocking on Netty's bind future. A bind failure escaped the message handler instead of failing the caller's Future.

Modification

  • Reply to each address query from a bind-future listener, capturing the requester before entering the callback. Branch directly on the completed future instead of throwing its cause through Try.
  • Report the bind cause through Status.Failure, including requests made after binding has already failed.
  • Cover ephemeral-port resolution and repeated queries after an occupied-port failure, and document the asynchronous behavior. The occupied-port test holds a listener with address reuse disabled on the exact loopback address used by the conductor.

Result

Address queries do not block the Controller or depend on the ordering of the query and bind completion. Failed binds consistently report their cause.

Tests

  • JDK 17: sbt "remote-tests / Test / testOnly org.apache.pekko.remote.testconductor.ControllerSpec" — 3 passed again after the review follow-up.

  • Directional regression on the previous PR implementation: the repeated failed-bind query timed out; 2 passed, 1 failed.

  • Native scalafmt, sbt headerCreateAll and git diff --check — passed.

  • sbt sortImports — environment failure in multi-node-testkit / scalafixAll and stream-tests / scalafixAll: NoSuchMethodError for scala.meta.package$.Input(). Unrelated import changes were discarded.

  • Initial-revision integration validation, before this review follow-up, on JDK 17: sbt headerCreateAll +mimaReportBinaryIssues +headerCheckAll checkCodeStyle docs/paradox — passed. Cross-version checks passed on Scala 2.13.18 and 3.3.8.

  • Initial-revision integration, before this review follow-up: sbt -Dpekko.test.tags.exclude=performance,timing,long-running -Dpekko.test.multi-in-test=false validatePullRequest — completed, but did not pass on macOS/arm64. LevelDB JNI lacks a compatible arm64 library (four persistence test forks failed); NettyTransportSpec could not bind the unavailable local address 127.0.1.1; two existing TCP readiness tests timed out. Docker-backed DNS tests were skipped because Docker was unavailable.

  • The two TCP failures passed when rerun in isolation against that revision's compiled integration code, without changing assertions or timeouts. The main-production baseline also exhibited a neighboring readiness timeout; those two exact cases did not fail in the repeated baseline runs. The full-run failures are retained in the validation record.

  • Follow-up validation: cross Scala multi-node-testkit MiMa and multi-node-testkit/remote-tests headers — passed on Scala 2.13.18 and 3.3.8. Scoped multi-node-testkit sortImports reproduced the existing Scalafix linkage error; native scalafmt and diff checks passed.

  • Follow-up integration with the other reviewed changes: ControllerSpec 3/3 and sbt docs/paradox passed. No new validatePullRequest run was performed, as requested.

References

Refs #3693. The runner's fixed default conductor port remains outside this change.

@pjfanning pjfanning added this to the 2.1.0 milestone Oct 25, 2026
@He-Pin
He-Pin force-pushed the fix-3693-controller-async-sockaddr branch from 5554332 to f276ada Compare October 25, 2026 10:44
@He-Pin He-Pin changed the title Answer GetSockAddr asynchronously in the testconductor Controller fix: answer conductor socket address queries asynchronously (#3693) Oct 25, 2026
Motivation:
The test conductor answered address queries by blocking on Netty's bind future. A bind failure escaped the message handler instead of failing the caller's Future.

Modification:
- Reply to each address query from a bind-future listener, capturing the requester before entering the callback. Branch directly on the completed future instead of throwing its cause through Try.
- Report the bind cause through Status.Failure, including requests made after binding has already failed.
- Cover ephemeral-port resolution and repeated queries after an occupied-port failure, and document the asynchronous behavior. The occupied-port test holds a listener with address reuse disabled on the exact loopback address used by the conductor.

Result:
Address queries do not block the Controller or depend on the ordering of the query and bind completion. Failed binds consistently report their cause.

Tests:
- JDK 17: sbt "remote-tests / Test / testOnly org.apache.pekko.remote.testconductor.ControllerSpec" — 3 passed again after the review follow-up.
- Directional regression on the previous PR implementation: the repeated failed-bind query timed out; 2 passed, 1 failed.
- Native scalafmt, sbt headerCreateAll and git diff --check — passed.
- sbt sortImports — environment failure in multi-node-testkit / scalafixAll and stream-tests / scalafixAll: NoSuchMethodError for scala.meta.package$.Input(). Unrelated import changes were discarded.
- Initial-revision integration validation, before this review follow-up, on JDK 17: `sbt headerCreateAll +mimaReportBinaryIssues +headerCheckAll checkCodeStyle docs/paradox` — passed. Cross-version checks passed on Scala 2.13.18 and 3.3.8.
- Initial-revision integration, before this review follow-up: `sbt -Dpekko.test.tags.exclude=performance,timing,long-running -Dpekko.test.multi-in-test=false validatePullRequest` — completed, but did not pass on macOS/arm64. LevelDB JNI lacks a compatible arm64 library (four persistence test forks failed); NettyTransportSpec could not bind the unavailable local address 127.0.1.1; two existing TCP readiness tests timed out. Docker-backed DNS tests were skipped because Docker was unavailable.
- The two TCP failures passed when rerun in isolation against that revision's compiled integration code, without changing assertions or timeouts. The main-production baseline also exhibited a neighboring readiness timeout; those two exact cases did not fail in the repeated baseline runs. The full-run failures are retained in the validation record.
- Follow-up validation: cross Scala multi-node-testkit MiMa and multi-node-testkit/remote-tests headers — passed on Scala 2.13.18 and 3.3.8. Scoped multi-node-testkit sortImports reproduced the existing Scalafix linkage error; native scalafmt and diff checks passed.

- Follow-up integration with the other reviewed changes: ControllerSpec 3/3 and `sbt docs/paradox` passed. No new `validatePullRequest` run was performed, as requested.

References:
Refs #3693. The runner's fixed default conductor port remains outside this change.
@He-Pin
He-Pin force-pushed the fix-3693-controller-async-sockaddr branch from f276ada to 3419e19 Compare October 26, 2026 03:58

@pjfanning pjfanning left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I think this is safe for 2.0.0.

Blast radius is small:

  • The change is confined to multi-node-testkit, which only runs inside multi-JVM test suites. No production code path is affected.
  • Within that module, only the Controller's GetSockAddr handler changes. Controller is private[pekko] and there are no API or binary changes.
  • The success path returns the same bound address as before; the reply is just sent from the bind-future listener instead of blocking the actor. The callers (startController / sockAddr) use ask, so the async reply has no ordering implications.
  • The failure path improves: a failed bind used to crash/restart the Controller and leave the caller with an ask timeout; now the caller gets the actual BindException promptly.

@He-Pin He-Pin modified the milestones: 2.1.0, 2.0.0-M5 Oct 26, 2026
@He-Pin
He-Pin merged commit c16b443 into main Oct 26, 2026
10 checks passed
@He-Pin
He-Pin deleted the fix-3693-controller-async-sockaddr branch October 26, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants