Skip to content

Commit e3d8dd4

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 41fcd88 commit e3d8dd4

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
@@ -392,23 +392,28 @@ def graphql_http_post_real(query)
392392
return { code: response.code.to_i, data: { "body" => response.body } }
393393
end
394394

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

453+
it "logs at warn and returns a retryable response for a read timeout" do
454+
timeout = Net::ReadTimeout.new
455+
stub_request(:post, "https://github.fake/api/v3/graphql").to_raise(timeout)
456+
expect(logger).to receive(:warn).with("#{timeout.class} #{timeout.message}")
457+
response = subject.send(:graphql_http_post_real, "nonsense")
458+
expect(response).to eq(code: 500, data: nil)
459+
end
460+
453461
it "logs at error and returns code=500 and exception message for an unhandled exception" do
454462
exc = StandardError.new("Oh no you don't")
455463
stub_request(:post, "https://github.fake/api/v3/graphql").to_raise(exc)

0 commit comments

Comments
 (0)