Steps to reproduce (logical sequence)
- Fallback host F succeeds and is stored as the preferred host via
setPreferredHost(F, true) - timer starts.
- A new request A begins.
getPreferredHost() returns F (not yet expired). candidateHost = F.
- Request A is in-flight against F for a duration that crosses
fallbackRetryTimeout.
- A concurrent request B begins.
getPreferredHost() finds the entry expired, clears it, and returns the primary host. Request B proceeds from primary — correct per RSC15f.
- Request A finishes successfully against F.
HttpScheduler line 206 calls setPreferredHost(F, true). Because preferred.host is now null (cleared by step 4), isHost(F) returns false and the early-return guard is skipped.
F is re-stored as the preferred host with a fresh timeout.
Expected behaviour
Once fallbackRetryTimeout has elapsed and the preference has been cleared, a successful response from the previously-preferred host should not re-establish that host as the preference. The
expiry event was authoritative; the in-flight request's outcome should not undo it.
Actual behaviour
The preferred host is restored with a new full fallbackRetryTimeout window, even though the system had already decided (correctly) to reset to primary for new requests.
┆Issue is synchronized with this Jira Task by Unito
Steps to reproduce (logical sequence)
setPreferredHost(F, true)- timer starts.getPreferredHost()returns F (not yet expired).candidateHost = F.fallbackRetryTimeout.getPreferredHost()finds the entry expired, clears it, and returns the primary host. Request B proceeds from primary — correct per RSC15f.HttpSchedulerline 206 callssetPreferredHost(F, true). Becausepreferred.hostis nownull(cleared by step 4),isHost(F)returnsfalseand the early-return guard is skipped.F is re-stored as the preferred host with a fresh timeout.
Expected behaviour
Once
fallbackRetryTimeouthas elapsed and the preference has been cleared, a successful response from the previously-preferred host should not re-establish that host as the preference. Theexpiry event was authoritative; the in-flight request's outcome should not undo it.
Actual behaviour
The preferred host is restored with a new full
fallbackRetryTimeoutwindow, even though the system had already decided (correctly) to reset to primary for new requests.┆Issue is synchronized with this Jira Task by Unito