Class: DiscordStore::Transport::NetHTTP

Inherits:
Object
  • Object
show all
Defined in:
lib/discord_store/transport/http.rb

Overview

Net::HTTP backend.

Connections are cached per (host, port) in fiber-local storage rather than thread-local. Under a fiber scheduler two fibers on one thread run concurrently, and sharing one Net::HTTP object between them interleaves bytes on the socket and corrupts both responses — the same failure that forced Rails to grow a fiber-aware connection pool, arriving here through a completely different door.

Instance Method Summary collapse

Constructor Details

#initialize(open_timeout: 5.0, read_timeout: 30.0, write_timeout: 30.0) ⇒ NetHTTP

Returns a new instance of NetHTTP.

Parameters:

  • open_timeout (Numeric) (defaults to: 5.0)
  • read_timeout (Numeric) (defaults to: 30.0)
  • write_timeout (Numeric) (defaults to: 30.0)


45
46
47
48
49
# File 'lib/discord_store/transport/http.rb', line 45

def initialize(open_timeout: 5.0, read_timeout: 30.0, write_timeout: 30.0)
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @write_timeout = write_timeout
end

Instance Method Details

#call(request) ⇒ Response

Parameters:

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/discord_store/transport/http.rb', line 53

def call(request)
  uri = URI.parse(request.url)
  http = connection_for(uri)

  net_request = build_request(request, uri)
  response = http.request(net_request)

  Response.new(
    status: response.code.to_i,
    headers: flatten_headers(response),
    body: response.body
  )
rescue Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout => e
  # A dead route that silently drops packets is indistinguishable from a
  # slow one, so every phase is bounded. Surfaced as a retryable 599.
  Response.new(status: 599, headers: {}, body: "#{e.class}: #{e.message}")
rescue SystemCallError, OpenSSL::SSL::SSLError, IOError => e
  drop_connection(uri)
  Response.new(status: 599, headers: {}, body: "#{e.class}: #{e.message}")
end

#close ⇒ void

This method returns an undefined value.

Closes every cached connection held by the current fiber.



77
78
79
80
# File 'lib/discord_store/transport/http.rb', line 77

def close
  connections.each_value { |http| http.finish if http.started? }
  connections.clear
end