Skip to content

Map transport failures to grpc-ruby errors - #9

Merged
samuel-williams-shopify merged 4 commits into
socketry:mainfrom
ekmartin:ek-conductor/fix-issue-5
Sep 24, 2026
Merged

samuel-williams-shopify merged 4 commits into
socketry:mainfrom
ekmartin:ek-conductor/fix-issue-5

Conversation

@ekmartin

@ekmartin ekmartin commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #5.

Transport failures escaped ClientStub#request_response as raw Ruby exceptions (Errno::ECONNREFUSED, EOFError, OpenSSL::SSL::SSLError, …), breaking code written against grpc-ruby's contract that every failure is a GRPC::BadStatus, such as GAPIC's UNAVAILABLE retry policies.

Changes

  • Connection, DNS, TLS, and HTTP/2 connection failures (including GOAWAY and refused requests) raise GRPC::Unavailable.
  • HTTP/2 stream resets use gRPC's HTTP/2 status mapping: REFUSED_STREAM → Unavailable, CANCEL → Cancelled, ENHANCE_YOUR_CALM → ResourceExhausted, INADEQUATE_SECURITY → PermissionDenied, and other reported stream errors → Internal.
  • The original exception is preserved as error.cause, and deferred operations record the status.
  • Only the transport is covered: errors raised by marshal and unmarshal callables are unchanged.
  • Requires protocol-grpc ~> 0.17, which preserves underlying body read errors (upstream fix). Transport errors propagate directly without a response-body wrapper.

TLS verification failures previously raised OpenSSL::SSL::SSLError and now raise GRPC::Unavailable, matching grpc-ruby; the TLS tests are updated accordingly.

Testing

  • Each mapped error type, real refused and closed connections, a server resetting the stream after response headers, a connection failing while reading the response, and GAPIC retrying a reset connection.
  • The new and updated tests fail without the fix.
  • Validated against published protocol-grpc 0.17.0: 122 tests, 436 assertions, and 100% line coverage. RuboCop and public API documentation coverage pass.

🤖 Generated with Claude Code

ekmartin and others added 3 commits September 24, 2026 10:36
Connection, DNS, TLS, and HTTP/2 connection failures now raise
`GRPC::Unavailable`, and HTTP/2 stream resets use gRPC's HTTP/2 status
mapping. The original exception is preserved as the cause, so retry
policies such as GAPIC's `UNAVAILABLE` retries apply.

The gRPC response body treats a failed stream as empty, so wrap it to
ensure stream errors are raised rather than reported as a missing status.

Fixes socketry#5.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@samuel-williams-shopify
samuel-williams-shopify merged commit 3663e1a into socketry:main Sep 24, 2026
11 checks passed
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.

Transport failures escape as raw socket errors instead of GRPC::Unavailable

2 participants