|
1 | 1 | require 'openssl' |
2 | | -require 'typhoeus' |
| 2 | +require 'faraday' |
| 3 | +require 'async' |
| 4 | +require 'async/barrier' |
| 5 | +require 'async/semaphore' |
3 | 6 |
|
4 | 7 | OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE |
5 | 8 |
|
|
14 | 17 | # - работает 1 секунду |
15 | 18 | # - одновременно можно запускать не более одного |
16 | 19 | # |
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 |
25 | 23 | end |
26 | 24 |
|
| 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 | + |
27 | 38 | def collect_sorted(arr) |
28 | | - arr.sort.join('-') |
| 39 | + arr.compact.sort.join('-') |
29 | 40 | end |
30 | 41 |
|
31 | 42 | start = Time.now |
32 | 43 |
|
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 |
35 | 64 |
|
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 |
42 | 68 |
|
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) |
48 | 77 | end |
49 | | -end |
50 | 78 |
|
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) } |
54 | 81 | 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 |
107 | 82 |
|
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 |
110 | 86 |
|
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