feat: add MUX method that waits for a connection.#708
Conversation
Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
|
I like it. Great idea. isConnected(timeout) is quite intuitive, so let's use it. |
Perhaps the argument that the `ISOSource` wouldn't connect after disconnection is not strong enough to limit the possibility of having it here. For instance, a MUX connected to a client channel adaptor that can receive responses in a different connection. Not a frequent scenario, but a probable one. Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
Consider the possibility that if the mux is not enabled at first, can be enabled during the timeout window Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
|
I reviewed this locally against the PR base ( Findings:
Verification: ./gradlew :jpos:test --tests org.jpos.q2.iso.QMUXTest --tests org.jpos.q2.iso.MUXPoolTestResult: git diff --check c2e712d...pr-708Result: failed with the whitespace issues listed above. Overall: useful feature direction and the focused tests pass, but I’d fix the whitespace before merge and consider simplifying |
…w feedback Replace the nested Future-based wait in MUXPool.isUsable(mux, timeout, executor) with CompletableFuture.allOf, so the connected and enabled/ready checks share a single timeout budget instead of the second get() silently getting less time than the first left it. Also documents QMUX.isConnected(timeout)'s fallback to running() when no <ready> indicators are configured, with a covering test, and fixes the trailing-whitespace / stray-blank-line issues flagged by review. Signed-off-by: Andrés Alcarraz <andres.alcarraz@transactility.com>
|
Re: point 2 ( I considered a plain deadline-poll loop instead (mirroring What I did fix is the actual bug behind the complexity: previously the two blocking waits ( The nested-future shape itself is what I'd expect real concurrent composition of two independent blocking waits to look like without a language-level structured-concurrency primitive. Whitespace and the If you still feel strongly about eliminating the nesting, I'm OK with implementing the polling version for now, and revisit this with structured concurrency once it exits the preview state. |
|
Given this uses virtual threads and the two waits now share a single timeout budget, I’m OK keeping the blocking Space-based implementation rather than switching back to polling. I'm re-running actions that were failing to see if it was a transient issue. |
This PR is more of an issue in disguise, and that is why it is maked as Draft. I've had this idea for some weeks now, and I figured it would be easy to propose a POC instead of describing what the added methods would do.
When we need to wait for a MUX to connect during some timeout, we usually end up doing some kind of polling, like in
QueryHost. But since the muxes detect the connection using a Space ready key, it would be better to just read the entry with a timeout.Of course, the developer could just do the read, but that would involve the developer knowing the key and type of mux it is using, leaving the code highly coupled.
This POC adds an
isConnected(long timeoutthat blocks until the timeout expires or the mux is connected. Perhaps the method should be called differently, likewaitForConnection, which expresses its meaning more clearly. I don't have a clear favourite.In the interface, we provide a default implementation that performs the usual polling. So it does not break other mux implementations. This should be both runtime and compile-time backward compatible.
I just realized that the method could be added to the
ISOSourceinterface instead, but I have mixed feelings about that. On one side, it doesn't cost anything, and it could cover more cases. On the flip side, it makes less sense semantically since a standard source would be connected and then disconnected, and not the other way around. However, we could think of some sources that are intermittently connected, e.g., strange setups where a "reverse" mux acting as a server can accept responses through a different connection than the request. Or some bidirectional communication implemented as a pair of "queues".In this POC, I also rewrote the
QueryHostparticipant to showcase how this would look.If this feature makes sense, I can try to improve this PR with some more time of dedication.
This POC also does not consider timeout of zero or negative a special case, i.e., they will return immediately as
isConnected()would, but we could consider some special case for indefinitely waiting, or just throw an exception on a negative value. I lightly prefer the current option because it's better for corner cases in the calling logic where the timeout just happens to compute to zero or negative, in which case the expected result would be to return immediately.This implementation could look cleaner with structured concurrency.