Skip to content

Commit 225c71e

Browse files
drbraindblock
authored andcommitted
Cache Faraday::Connection for persistent adapters
In order to be a good web citizen and to allow maximum performance HTTP clients should use persistent connections to make requests. This has multiple benefits: * Users won't be delayed by TCP slow-start figuring out the window size for every HTTP request * Users won't be delayed by TLS handshakes for each new request * Bandwidth overhead per request is reduced through large TCP windows on established TLS connections. Some Slack endpoints are paginated and may take many requests to fetch all necessary data. Using persistent connections can result in a 4x speed boost. Slack::Web::Client uses Faraday which uses Net::HTTP by default. While Net::HTTP is capable of persistent connections Net::HTTP + Faraday is not configured this way. The Faraday::Adapter::NetHttpPersistent adapter does. Slack::Web::Client uses Faraday#default_adapter so the end user can switch adapters are used like this: Faraday.default_adapter = Faraday::Adapter::NetHttpPersistent c = Slack::Web::Client.new … Unfortunately Slack::Web::Client does not cache the Faraday::Connection object and instead creates a new connection for every request. This breaks the ability to use persistent connections with Slack::Web::Client. This can be observed through using Wireshark with an `ssl.handshake` filter, or by observing `SYN` packets sent by `tcpdump host slack.com`. This patch adds caching of the Faraday::Connection object to Slack::Web::Client to allow caching of connections through Faraday. A cached connection can be reused as a persistent connection. Recommending users use a persistent connection adapter (like Faraday::Adapter::NetHttpPersistent) is not part of this pull request, but I do recommend it. Your users should see an easy speed improvement. Here is a `time` output from a script that fetches ~4,000 conversations using the net-http-persistent adapter without this patch (making it ineffective): $ time ruby t.rb ruby t.rb 2.46s user 0.25s system 14% cpu 18.389 total and with this patch: $ time ruby t.rb ruby t.rb 0.99s user 0.20s system 13% cpu 9.053 total (This is only a 2x speed boost as the slack `conversation.list` API is highly variable in response time.)
1 parent 6f49e2b commit 225c71e

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### 0.14.7 (Next)
22

3+
* [#322](https://github.com/slack-ruby/slack-ruby-client/pull/322): Cache `Faraday::Connection` for persistent adapters - [@drbrain](https://github.com/drbrain).
34
* Your contribution here.
45

56
### 0.14.6 (2020/3/28)

lib/slack/web/faraday/connection.rb

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,32 @@ module Connection
66
private
77

88
def connection
9-
options = {
10-
headers: { 'Accept' => 'application/json; charset=utf-8' }
11-
}
9+
@connection ||=
10+
begin
11+
options = {
12+
headers: { 'Accept' => 'application/json; charset=utf-8' }
13+
}
1214

13-
options[:headers]['User-Agent'] = user_agent if user_agent
14-
options[:proxy] = proxy if proxy
15-
options[:ssl] = { ca_path: ca_path, ca_file: ca_file } if ca_path || ca_file
15+
options[:headers]['User-Agent'] = user_agent if user_agent
16+
options[:proxy] = proxy if proxy
17+
options[:ssl] = { ca_path: ca_path, ca_file: ca_file } if ca_path || ca_file
1618

17-
request_options = {}
18-
request_options[:timeout] = timeout if timeout
19-
request_options[:open_timeout] = open_timeout if open_timeout
20-
options[:request] = request_options if request_options.any?
19+
request_options = {}
20+
request_options[:timeout] = timeout if timeout
21+
request_options[:open_timeout] = open_timeout if open_timeout
22+
options[:request] = request_options if request_options.any?
2123

22-
::Faraday::Connection.new(endpoint, options) do |connection|
23-
connection.use ::Faraday::Request::Multipart
24-
connection.use ::Faraday::Request::UrlEncoded
25-
connection.use ::Faraday::Response::RaiseError
26-
connection.use ::Slack::Web::Faraday::Response::RaiseError
27-
connection.use ::FaradayMiddleware::Mashify, mash_class: Slack::Messages::Message
28-
connection.use ::FaradayMiddleware::ParseJson
29-
connection.response :logger, logger if logger
30-
connection.adapter ::Faraday.default_adapter
31-
end
24+
::Faraday::Connection.new(endpoint, options) do |connection|
25+
connection.use ::Faraday::Request::Multipart
26+
connection.use ::Faraday::Request::UrlEncoded
27+
connection.use ::Faraday::Response::RaiseError
28+
connection.use ::Slack::Web::Faraday::Response::RaiseError
29+
connection.use ::FaradayMiddleware::Mashify, mash_class: Slack::Messages::Message
30+
connection.use ::FaradayMiddleware::ParseJson
31+
connection.response :logger, logger if logger
32+
connection.adapter ::Faraday.default_adapter
33+
end
34+
end
3235
end
3336
end
3437
end

spec/slack/web/client_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,5 +205,16 @@
205205
client.users_admin_setInactive(user: 'U092BDCLV')
206206
end
207207
end
208+
209+
context 'persistent capability' do
210+
describe '#initialize' do
211+
it 'caches the Faraday connection to allow persistent adapters' do
212+
first = client.send(:connection)
213+
second = client.send(:connection)
214+
215+
expect(first).to equal second
216+
end
217+
end
218+
end
208219
end
209220
end

0 commit comments

Comments
 (0)