Problem
DataPort.connect(NatsConnection conn, NatsUri nuri, long timeoutNanos) permanently binds the conn reference at connect time. Any DataPort implementation that stores conn for lifecycle management (e.g. a write-timeout watchdog that calls conn.forceReconnect()) remains wired to the connection that originally established the socket.
After the AP socket steal, the stolen DataPort is now owned by the active ApConnection, but its stored conn still points to oldPassive. Any lifecycle event on that DataPort — write-timeout watchdog, periodic probe, etc. — will call oldPassive.forceReconnect() instead of the active connection's forceReconnect(). This means:
- Write timeouts on the active connection are escalated to the wrong connection object
oldPassive.forceReconnect() triggers base reconnectImplConnect() → "Connection refused" loop
- Active's own timeout handler is never invoked
Proposed fix
Add a reattach lifecycle method to the DataPort interface in jnats:
// In DataPort interface (io.nats.client.impl.DataPort)
/**
* Called after a socket-steal transfers this DataPort to a new NatsConnection.
* Implementations should rebind any stored connection reference and restart any
* per-connection lifecycle tasks (e.g. write-timeout watchdogs) on the new owner.
*
* @param newConnection the NatsConnection that now owns this DataPort
*/
default void reattach(NatsConnection newConnection) {
// default no-op for implementations without lifecycle state
}
ApConnection.reconnectImplConnect() would call stolenDataPort.reattach(this) after the steal.
Current workaround
We added a reattachToConnection(NatsConnection) method to our own DataPort subclass and call it from within the split-package ApConnection after the steal. This is not a portable solution for third-party DataPort implementations.
Problem
DataPort.connect(NatsConnection conn, NatsUri nuri, long timeoutNanos)permanently binds theconnreference at connect time. AnyDataPortimplementation that storesconnfor lifecycle management (e.g. a write-timeout watchdog that callsconn.forceReconnect()) remains wired to the connection that originally established the socket.After the AP socket steal, the stolen
DataPortis now owned by the activeApConnection, but its storedconnstill points tooldPassive. Any lifecycle event on thatDataPort— write-timeout watchdog, periodic probe, etc. — will calloldPassive.forceReconnect()instead of the active connection'sforceReconnect(). This means:oldPassive.forceReconnect()triggers basereconnectImplConnect()→ "Connection refused" loopProposed fix
Add a reattach lifecycle method to the
DataPortinterface in jnats:ApConnection.reconnectImplConnect()would callstolenDataPort.reattach(this)after the steal.Current workaround
We added a
reattachToConnection(NatsConnection)method to our ownDataPortsubclass and call it from within the split-packageApConnectionafter the steal. This is not a portable solution for third-partyDataPortimplementations.