Reset keep-alive connections retry instead of raising a raw Faraday error
A focused fix release for the request retry mechanism. The SDK's persistent
connection pool could hand a request a connection the server or a load
balancer had already closed after idling; the request then failed immediately
with a raw Faraday::ConnectionFailed (Errno::ECONNRESET) even though an
immediate re-send on a fresh connection succeeds. Reset connections now retry
under the same idempotency rules as read timeouts.
Changes
- FIXED:
Parse::Client#requestnow rescuesFaraday::ConnectionFailed
and splits it on the wrapped cause. Reset-class causes (Errno::ECONNRESET,
Errno::EPIPE,Errno::ECONNABORTED, and theEOFErrorraised when the
remote end closes a keep-alive socket cleanly) are transient, so idempotent
requests (GET, DELETE, op-free PUT, and any write covered by asserted
server-side request-id dedup) retry with the standard linear backoff and
jitter. Connection refused and DNS failures keep the previous fail-fast
behavior and propagate the rawFaraday::ConnectionFailedwith no retry
latency. POSTs and atomic-op PUTs are still never replayed without server
dedup, since a reset mid-write leaves the outcome unknown. - CHANGED: A reset connection that persists through the whole retry budget
now raisesParse::Error::ConnectionError, consistent with the read-timeout
path, instead of the rawFaraday::ConnectionFailed. Code that rescued
Faraday::ConnectionFailedto catch resets should rescue
Parse::Error::ConnectionErrorinstead; refused and DNS failures still
raiseFaraday::ConnectionFailed. - CHANGED: Bumped locked dependencies and CI actions to their latest
compatible releases:graphql2.6.8 → 2.6.10,github/codeql-action
4.37.6 → 4.37.9, andrubygems/release-gem1.4.0 → 1.4.1.
Behavior Notes
Retries apply only to requests whose replay is safe. A reset during a
non-idempotent write still fails immediately, now as
Parse::Error::ConnectionError, so nothing can double-apply.
Commit: d7de7ba
Author: Adrian Curtin
Date: September 8, 2026