Skip to content

Commit 4189785

Browse files
committed
refact: Use Async
1 parent 6f06945 commit 4189785

3 files changed

Lines changed: 68 additions & 91 deletions

File tree

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ gem "async"
44
gem "falcon", "0.44.0" # use different version on your own risk; 0.44.0 worked
55
gem "sinatra"
66
gem "faraday"
7-
gem "typhoeus"

Gemfile.lock

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ GEM
3030
fiber-annotation
3131
fiber-local (~> 1.1)
3232
json
33-
ethon (0.16.0)
34-
ffi (>= 1.15.0)
3533
falcon (0.44.0)
3634
async
3735
async-container (~> 0.17)
@@ -49,8 +47,6 @@ GEM
4947
faraday-net_http (>= 2.0, < 3.2)
5048
faraday-net_http (3.1.0)
5149
net-http
52-
ffi (1.17.1)
53-
ffi (1.17.1-x86_64-darwin)
5450
fiber-annotation (0.2.0)
5551
fiber-local (1.1.0)
5652
fiber-storage
@@ -96,8 +92,6 @@ GEM
9692
tilt (2.3.0)
9793
timers (4.3.5)
9894
traces (0.11.1)
99-
typhoeus (1.4.1)
100-
ethon (>= 0.9.0)
10195
uri (0.13.0)
10296

10397
PLATFORMS
@@ -109,7 +103,6 @@ DEPENDENCIES
109103
falcon (= 0.44.0)
110104
faraday
111105
sinatra
112-
typhoeus
113106

114107
BUNDLED WITH
115108
2.5.11

client.rb

Lines changed: 68 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
require 'openssl'
2-
require 'typhoeus'
2+
require 'faraday'
3+
require 'async'
4+
require 'async/barrier'
5+
require 'async/semaphore'
36

47
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
58

@@ -14,99 +17,81 @@
1417
# - работает 1 секунду
1518
# - одновременно можно запускать не более одного
1619
#
17-
def make_request(endpoint, value)
18-
Typhoeus::Request.new(
19-
"https://localhost:9292/#{endpoint}",
20-
method: :get,
21-
params: { value: value },
22-
ssl_verifypeer: false,
23-
timeout: 10
24-
)
20+
def a(value)
21+
puts "https://localhost:9292/a?value=#{value}"
22+
Faraday.get("https://localhost:9292/a?value=#{value}").body
2523
end
2624

25+
def b(value)
26+
puts "https://localhost:9292/b?value=#{value}"
27+
Faraday.get("https://localhost:9292/b?value=#{value}").body
28+
end
29+
30+
def c(value)
31+
puts "https://localhost:9292/c?value=#{value}"
32+
Faraday.get("https://localhost:9292/c?value=#{value}").body
33+
end
34+
35+
# Референсное решение, приведённое ниже работает правильно, занимает ~19.5 секунд
36+
# Надо сделать в пределах 7 секунд
37+
2738
def collect_sorted(arr)
28-
arr.sort.join('-')
39+
arr.compact.sort.join('-')
2940
end
3041

3142
start = Time.now
3243

33-
hydra = Typhoeus::Hydra.new(max_concurrency: 6)
34-
responses = {}
44+
result = Async do
45+
barrier = Async::Barrier.new
46+
semaphore_a = Async::Semaphore.new(3, parent: barrier)
47+
semaphore_b = Async::Semaphore.new(2, parent: barrier)
48+
semaphore_c = Async::Semaphore.new(1, parent: barrier)
49+
50+
a_results = {
51+
batch1: Array.new(3),
52+
batch2: Array.new(3),
53+
batch3: Array.new(3)
54+
}
55+
b_results = Array.new(3)
56+
c_results = Array.new(3)
57+
58+
3.times do |i|
59+
semaphore_a.async do
60+
a_results[:batch1][i] = a(11 + i)
61+
a_results[:batch2][i] = a(21 + i)
62+
end
63+
end
3564

36-
a_batches = {
37-
1 => [11, 12, 13].map { |v| make_request('a', v) },
38-
2 => [21, 22, 23].map { |v| make_request('a', v) },
39-
3 => [31, 32, 33].map { |v| make_request('a', v) }
40-
}
41-
b_requests = [1, 2, 3].map { |v| make_request('b', v) }
65+
2.times do |i|
66+
semaphore_b.async { b_results[i] = b(i + 1) }
67+
end
4268

43-
a_batches.each do |batch, reqs|
44-
reqs.each do |req|
45-
req.on_complete do |response|
46-
responses["a#{batch}_#{req.options[:params][:value]}".to_sym] = response.body
47-
end
69+
barrier.wait
70+
71+
ab1 = "#{collect_sorted(a_results[:batch1])}-#{b_results[0]}"
72+
ab2 = "#{collect_sorted(a_results[:batch2])}-#{b_results[1]}"
73+
74+
semaphore_c.async do
75+
c_results[0] = c(ab1)
76+
c_results[1] = c(ab2)
4877
end
49-
end
5078

51-
b_requests.each_with_index do |req, idx|
52-
req.on_complete do |response|
53-
responses["b_#{idx + 1}".to_sym] = response.body
79+
3.times do |i|
80+
semaphore_a.async { a_results[:batch3][i] = a(31 + i) }
5481
end
55-
end
56-
# Queue first batch
57-
a_batches[1].each { |req| hydra.queue(req) }
58-
[b_requests[0], b_requests[1]].each { |req| hydra.queue(req) }
59-
# Run first batch
60-
hydra.run
61-
62-
# Queue second batch
63-
ab1 = "#{collect_sorted(a_batches[1].map! { |req| responses["a1_#{req.options[:params][:value]}".to_sym] })}-#{responses[:b_1]}"
64-
puts "AB1 = #{ab1}"
65-
c1_req = make_request('c', ab1)
66-
c1_req.on_complete { |response| responses[:c1] = response.body }
67-
hydra.queue(c1_req)
68-
69-
a_batches[2].each { |req| hydra.queue(req) }
70-
hydra.queue(b_requests[2])
71-
# Run second batch
72-
hydra.run
73-
74-
ab2 = "#{collect_sorted(a_batches[2].map! { |req| responses["a2_#{req.options[:params][:value]}".to_sym] })}-#{responses[:b_2]}"
75-
puts "C1 = #{responses[:c1]}"
76-
puts "AB2 = #{ab2}"
77-
78-
# Queue third batch
79-
c2_req = make_request('c', ab2)
80-
c2_req.on_complete { |response| responses[:c2] = response.body }
81-
hydra.queue(c2_req)
82-
a_batches[3].each { |req| hydra.queue(req) }
83-
84-
# Run third batch
85-
hydra.run
86-
87-
puts "C2 = #{responses[:c2]}"
88-
ab3 = "#{collect_sorted(a_batches[3].map! { |req| responses["a3_#{req.options[:params][:value]}".to_sym] })}-#{responses[:b_3]}"
89-
puts "AB3 = #{ab3}"
90-
91-
# Queue fourth batch
92-
c3_req = make_request('c', ab3)
93-
c3_req.on_complete { |response| responses[:c3] = response.body }
94-
hydra.queue(c3_req)
95-
96-
# Run fourth batch
97-
hydra.run
98-
99-
puts "C3 = #{responses[:c3]}"
100-
c123 = collect_sorted([responses[:c1], responses[:c2], responses[:c3]])
101-
102-
# Final processing
103-
final_req = make_request('a', c123)
104-
final_req.on_complete { |response| responses[:final] = response.body }
105-
hydra.queue(final_req)
106-
hydra.run
10782

108-
puts "FINISHED in #{Time.now - start}s."
109-
puts "RESULT = #{responses[:final]}" # 0bbe9ecf251ef4131dd43e1600742cfb
83+
semaphore_b.async { b_results[2] = b(3) }
84+
85+
barrier.wait
11086

111-
# FINISHED in 7.064975s.
112-
# RESULT = 0bbe9ecf251ef4131dd43e1600742cfb
87+
ab3 = "#{collect_sorted(a_results[:batch3])}-#{b_results[2]}"
88+
semaphore_c.async { c_results[2] = c(ab3) }
89+
90+
barrier.wait
91+
92+
c123 = collect_sorted(c_results)
93+
a(c123)
94+
end.wait
95+
96+
puts "FINISHED in #{Time.now - start}s."
97+
puts "RESULT = #{result}" # 0bbe9ecf251ef4131dd43e1600742cfb

0 commit comments

Comments
 (0)