Skip to content

Commit c321b89

Browse files
committed
Initial implementation (not working).
1 parent 16d6ad1 commit c321b89

File tree

3 files changed

+97
-2
lines changed

3 files changed

+97
-2
lines changed

gems.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
gemspec
99

10+
gem "faraday", git: "https://github.com/lostisland/faraday.git", branch: "mg/parallel-manager-execute"
11+
1012
group :maintenance, optional: true do
1113
gem "bake-modernize"
1214
gem "bake-gem"

lib/async/http/faraday/adapter.rb

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
require 'faraday'
1414
require 'faraday/adapter'
15+
16+
require 'async/barrier'
1517
require 'kernel/sync'
1618

1719
require 'async/http/client'
@@ -48,8 +50,41 @@ def read
4850
end
4951
end
5052

53+
class ParallelManager
54+
def initialize(options = {})
55+
@options = options
56+
@barrier = nil
57+
end
58+
59+
def run
60+
raise NotImplementedError, "Please update your Faraday version!"
61+
end
62+
63+
def async(&block)
64+
@barrier.async(&block)
65+
end
66+
67+
def execute(&block)
68+
Sync do
69+
@barrier = Async::Barrier.new
70+
71+
yield
72+
73+
@barrier.wait
74+
ensure
75+
@barrier&.stop
76+
end
77+
end
78+
end
79+
5180
# An adapter that allows Faraday to use Async::HTTP as the underlying HTTP client.
5281
class Adapter < ::Faraday::Adapter
82+
self.supports_parallel = true
83+
84+
def self.setup_parallel_manager(**options)
85+
ParallelManager.new(options)
86+
end
87+
5388
# The exceptions that are considered connection errors and result in a `Faraday::ConnectionFailed` exception.
5489
CONNECTION_EXCEPTIONS = [
5590
Errno::EADDRNOTAVAIL,
@@ -98,6 +133,23 @@ def call(env)
98133
# For compatibility with the default adapter:
99134
env.url.path = '/' if env.url.path.empty?
100135

136+
if parallel_manager = env.parallel_manager
137+
parallel_manager.async do
138+
perform_request(env)
139+
140+
# Do I need this line?
141+
env.response.finish(env)
142+
end
143+
else
144+
perform_request(env)
145+
end
146+
147+
return env.response
148+
end
149+
150+
private
151+
152+
def perform_request(env)
101153
with_client(env) do |endpoint, client|
102154
if body = env.body
103155
# We need to ensure the body is wrapped in a Readable object so that it can be read in chunks:
@@ -149,8 +201,6 @@ def call(env)
149201
raise ::Faraday::ConnectionFailed, e
150202
end
151203

152-
private
153-
154204
def with_client(env)
155205
Sync do
156206
endpoint = Endpoint.new(env.url)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2024, by Samuel Williams.
5+
6+
require 'async/http/faraday'
7+
8+
require 'sus/fixtures/async/reactor_context'
9+
require 'sus/fixtures/async/http/server_context'
10+
11+
describe Async::HTTP::Faraday::Adapter do
12+
with "a local http server" do
13+
include Sus::Fixtures::Async::ReactorContext
14+
include Sus::Fixtures::Async::HTTP::ServerContext
15+
16+
17+
let(:app) do
18+
Protocol::HTTP::Middleware.for do |request|
19+
Protocol::HTTP::Response[200, {}, ['Hello World']]
20+
end
21+
end
22+
23+
it "client can get resource" do
24+
adapter = Faraday.new(bound_url) do |builder|
25+
builder.adapter :async_http
26+
end
27+
28+
response1 = response2 = response3 = nil
29+
30+
adapter.in_parallel do
31+
response1 = adapter.get("/index")
32+
response2 = adapter.get("/index")
33+
resposne3 = adapter.get("/index")
34+
end
35+
36+
expect(response1.body).to be == 'Hello World'
37+
expect(response2.body).to be == 'Hello World'
38+
expect(response3.body).to be == 'Hello World'
39+
ensure
40+
adapter&.close
41+
end
42+
end
43+
end

0 commit comments

Comments
 (0)