forked from Shopify/graphql-batch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
http_loader.rb
65 lines (61 loc) · 1.65 KB
/
http_loader.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# A sample HTTP loader using:
#
# 1. https://github.com/httprb/http
# 2. https://github.com/mperham/connection_pool
# 3. https://github.com/ruby-concurrency/concurrent-ruby
#
# Setup:
#
# field :weather, String, null: true do
# argument :lat, Float, required: true
# argument :lng, Float, required: true
# argument :lang, String, required: true
# end
#
# def weather(lat:, lng:, lang:)
# key = Rails.application.credentials.darksky_key
# path = "/forecast/#{key}/#{lat},#{lng}?lang=#{lang}"
# Loaders::HTTPLoader
# .for(host: 'https://api.darksky.net')
# .load(->(connection) { connection.get(path).flush })
# .then do |response|
# if response.status.ok?
# json = JSON.parse(response.body)
# json['currently']['summary']
# end
# end
# end
#
# Querying:
#
# <<~GQL
# query Weather {
# montreal: weather(lat: 45.5017, lng: -73.5673, lang: "fr")
# waterloo: weather(lat: 43.4643, lng: -80.5204, lang: "en")
# }
# GQL
module Loaders
class HTTPLoader < GraphQL::Batch::Loader
def initialize(host:, size: 4, timeout: 4)
@host = host
@size = size
@timeout = timeout
end
def perform(operations)
futures = operations.map do |operation|
Concurrent::Promises.future do
pool.with { |connection| operation.call(connection) }
end
end
operations.each_with_index.each do |operation, index|
fulfill(operation, futures[index].value)
end
end
private
def pool
@pool ||= ConnectionPool.new(size: @size, timeout: @timeout) do
HTTP.persistent(@host)
end
end
end
end