Skip to content

Commit 91a366e

Browse files
committed
fix(github): catch network ReadTimeout
Today we got a ERROR -- : Caught Net::ReadTimeout POSTing to https://api.github.com/graphql: Net::ReadTimeout with #<TCPSocket:(closed)> This is not worthy of an ERROR; it's safe to just retry. Turns out we didn't have any rescue for this case, so I've added it. I've also flattened the file a little bit, having a global rescue list instead of splitting them.
1 parent 03740a8 commit 91a366e

3 files changed

Lines changed: 30 additions & 17 deletions

File tree

‎lib/entitlements/service/github.rb‎

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -390,23 +390,28 @@ def graphql_http_post_real(query)
390390
return { code: response.code.to_i, data: { "body" => response.body } }
391391
end
392392

393-
begin
394-
data = JSON.parse(response.body)
395-
if data.key?("errors")
396-
# Synthesized 500 below triggers a retry, so log at WARN. Note: some GraphQL
397-
# `errors` are permanent (bad query, auth, schema). The retry wrapper's final
398-
# "Giving up" ERROR will surface persistent cases.
399-
Entitlements.logger.warn "Errors reported: #{data['errors'].inspect}"
400-
return { code: 500, data: }
401-
end
402-
{ code: response.code.to_i, data: }
403-
rescue JSON::ParserError => e
404-
# JSON parse errors mean the API returned something we can't interpret. The
405-
# synthesized 500 below triggers a retry, but the cause is more likely a real
406-
# protocol/server problem than a transient network blip, so log at ERROR.
407-
Entitlements.logger.error "#{e.class} #{e.message}: #{response.body.inspect}"
408-
{ code: 500, data: { "body" => response.body } }
393+
data = JSON.parse(response.body)
394+
if data.key?("errors")
395+
# Synthesized 500 below triggers a retry, so log at WARN. Note: some GraphQL
396+
# `errors` are permanent (bad query, auth, schema). The retry wrapper's final
397+
# "Giving up" ERROR will surface persistent cases.
398+
Entitlements.logger.warn "Errors reported: #{data['errors'].inspect}"
399+
return { code: 500, data: }
409400
end
401+
402+
{ code: response.code.to_i, data: }
403+
404+
rescue Net::ReadTimeout => e
405+
# Defend against network blips, those can be safely retried via the
406+
# synthesized 500 below, so log at WARN.
407+
Entitlements.logger.warn "#{e.class} #{e.message}"
408+
{ code: 500, data: nil }
409+
rescue JSON::ParserError => e
410+
# JSON parse errors mean the API returned something we can't interpret. The
411+
# synthesized 500 below triggers a retry, but the cause is more likely a real
412+
# protocol/server problem than a transient network blip, so log at ERROR.
413+
Entitlements.logger.error "#{e.class} #{e.message}: #{response.body.inspect}"
414+
{ code: 500, data: { "body" => response.body } }
410415
rescue => e
411416
# Catch-all for any unexpected exception (network blip OR local code bug).
412417
# We retry below via the synthesized 500, but log at ERROR because this

‎lib/version.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
module Entitlements
44
module Version
5-
VERSION = "1.2.2"
5+
VERSION = "1.2.3"
66
end
77
end

‎spec/unit/entitlements/service/github_spec.rb‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,14 @@
368368
expect(response).to eq(code: 200, data: answer)
369369
end
370370

371+
it "logs at warn and returns a retryable response for a read timeout" do
372+
timeout = Net::ReadTimeout.new
373+
stub_request(:post, "https://github.fake/api/v3/graphql").to_raise(timeout)
374+
expect(logger).to receive(:warn).with("#{timeout.class} #{timeout.message}")
375+
response = subject.send(:graphql_http_post_real, "nonsense")
376+
expect(response).to eq(code: 500, data: nil)
377+
end
378+
371379
it "logs at error and returns code=500 and exception message for an unhandled exception" do
372380
exc = StandardError.new("Oh no you don't")
373381
stub_request(:post, "https://github.fake/api/v3/graphql").to_raise(exc)

0 commit comments

Comments
 (0)