umbra-rb 0.2.0 → 0.3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12773099d5e69ca31d44d8751335f2dd7652c3d37626be3f7e69ba1048f2d8eb
4
- data.tar.gz: 7d29a4d0c0bf0e7c715a88e8696e99b9c92e2eb590738edab34b62e334e900e6
3
+ metadata.gz: b78a47b9846524b89aa167c590d5f912fec5b15e3f257f131bec39717469cbc5
4
+ data.tar.gz: '0638dcec00b31af9ef1acb84969fef4dcab5cab1ad24453e52fea11491275655'
5
5
  SHA512:
6
- metadata.gz: e7ba308273cf8ab2d97d12081e03449b220972b1f9759613f99507b956f29c6538ff3aa11c9e5fbced6326878fbb096393ab95fa2659c0b3410b835a94f2966d
7
- data.tar.gz: a3e54eb44ff862456c5d474e38fd5058f358e5a36264bd65aaffed18861baa456a65259d890b069e40554d2bda7515e9d412e94d62d048b48671f2a1487cf0f6
6
+ metadata.gz: 38b6958b37872340e07ae3e0f0f18371ae2a7e27787a2521fe9eda8962f8f5e1c7355177677650e811b2e5ba5b1fefb2e228a56993c3a774147191e1df289fe8
7
+ data.tar.gz: 6255267c65a90494b301367ccd14645a3e4dc8c481115155fd6c60e94ce1f4ad64d4125b13de2b48d83e84132da1df3a2602689ff35a213f25df2c1dcea30566
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- umbra-rb (0.2.0)
4
+ umbra-rb (0.3.0.pre)
5
+ concurrent-ruby (~> 1.1)
5
6
  multi_json (~> 1.13)
6
7
  oj (~> 3.9)
7
8
  redis (~> 4.1)
@@ -10,57 +11,70 @@ PATH
10
11
  GEM
11
12
  remote: https://rubygems.org/
12
13
  specs:
14
+ addressable (2.7.0)
15
+ public_suffix (>= 2.0.2, < 5.0)
13
16
  ast (2.4.0)
14
- carwow_rubocop (3.0.3)
15
- rubocop (>= 0.68)
17
+ carwow_rubocop (3.2.1)
18
+ rubocop (>= 0.78)
16
19
  rubocop-performance
17
20
  rubocop-rspec
18
21
  coderay (1.1.2)
22
+ concurrent-ruby (1.1.5)
23
+ crack (0.4.3)
24
+ safe_yaml (~> 1.0.0)
19
25
  diff-lcs (1.3)
20
26
  ethon (0.12.0)
21
27
  ffi (>= 1.3.0)
22
- ffi (1.11.1)
23
- jaro_winkler (1.5.3)
28
+ ffi (1.12.1)
29
+ hashdiff (1.0.0)
30
+ jaro_winkler (1.5.4)
24
31
  method_source (0.9.2)
25
- multi_json (1.13.1)
26
- oj (3.9.2)
27
- parallel (1.17.0)
28
- parser (2.6.4.1)
32
+ multi_json (1.14.1)
33
+ oj (3.10.1)
34
+ parallel (1.19.1)
35
+ parser (2.7.0.2)
29
36
  ast (~> 2.4.0)
30
37
  pry (0.12.2)
31
38
  coderay (~> 1.1.0)
32
39
  method_source (~> 0.9.0)
40
+ public_suffix (4.0.3)
41
+ rack (2.1.1)
33
42
  rainbow (3.0.0)
34
- rake (10.5.0)
43
+ rake (13.0.1)
35
44
  redis (4.1.3)
36
- rspec (3.8.0)
37
- rspec-core (~> 3.8.0)
38
- rspec-expectations (~> 3.8.0)
39
- rspec-mocks (~> 3.8.0)
40
- rspec-core (3.8.2)
41
- rspec-support (~> 3.8.0)
42
- rspec-expectations (3.8.4)
45
+ rspec (3.9.0)
46
+ rspec-core (~> 3.9.0)
47
+ rspec-expectations (~> 3.9.0)
48
+ rspec-mocks (~> 3.9.0)
49
+ rspec-core (3.9.0)
50
+ rspec-support (~> 3.9.0)
51
+ rspec-expectations (3.9.0)
43
52
  diff-lcs (>= 1.2.0, < 2.0)
44
- rspec-support (~> 3.8.0)
45
- rspec-mocks (3.8.1)
53
+ rspec-support (~> 3.9.0)
54
+ rspec-mocks (3.9.0)
46
55
  diff-lcs (>= 1.2.0, < 2.0)
47
- rspec-support (~> 3.8.0)
48
- rspec-support (3.8.2)
49
- rubocop (0.74.0)
56
+ rspec-support (~> 3.9.0)
57
+ rspec-support (3.9.0)
58
+ rubocop (0.79.0)
50
59
  jaro_winkler (~> 1.5.1)
51
60
  parallel (~> 1.10)
52
- parser (>= 2.6)
61
+ parser (>= 2.7.0.1)
53
62
  rainbow (>= 2.2.2, < 4.0)
54
63
  ruby-progressbar (~> 1.7)
55
64
  unicode-display_width (>= 1.4.0, < 1.7)
56
- rubocop-performance (1.4.1)
65
+ rubocop-performance (1.5.2)
57
66
  rubocop (>= 0.71.0)
58
- rubocop-rspec (1.35.0)
59
- rubocop (>= 0.60.0)
67
+ rubocop-rspec (1.37.1)
68
+ rubocop (>= 0.68.1)
60
69
  ruby-progressbar (1.10.1)
70
+ safe_yaml (1.0.5)
61
71
  typhoeus (1.3.1)
62
72
  ethon (>= 0.9.0)
63
73
  unicode-display_width (1.6.0)
74
+ webmock (3.8.0)
75
+ addressable (>= 2.3.6)
76
+ crack (>= 0.3.2)
77
+ hashdiff (>= 0.4.0, < 2.0.0)
64
78
 
65
79
  PLATFORMS
66
80
  ruby
@@ -69,9 +83,11 @@ DEPENDENCIES
69
83
  bundler (~> 2.0)
70
84
  carwow_rubocop
71
85
  pry
72
- rake (~> 10.0)
86
+ rack
87
+ rake (~> 13.0)
73
88
  rspec (~> 3.0)
74
89
  umbra-rb!
90
+ webmock (~> 3)
75
91
 
76
92
  BUNDLED WITH
77
93
  2.0.2
data/config.ru ADDED
@@ -0,0 +1,8 @@
1
+ require 'rack'
2
+ require 'rack/lobster'
3
+ require 'umbra'
4
+
5
+ Umbra.configure
6
+
7
+ use Umbra::Middleware
8
+ run Rack::Lobster.new
data/lib/umbra.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'typhoeus'
4
4
  require 'redis'
5
5
  require 'multi_json'
6
+ require 'concurrent'
6
7
 
7
8
  module Umbra
8
9
  autoload :Config, 'umbra/config'
data/lib/umbra/config.rb CHANGED
@@ -4,7 +4,7 @@ module Umbra
4
4
 
5
5
  def self.default(&block)
6
6
  new(
7
- publisher: Publisher,
7
+ publisher: Publisher.new,
8
8
  request_selector: RequestSelector,
9
9
  encoder: Encoder,
10
10
  error_handler: SuppressErrorHandler,
@@ -1,55 +1,30 @@
1
1
  module Umbra
2
- class Publisher < SynchronousPublisher
3
- MAX_QUEUE_SIZE = 100
4
-
5
- class << self
6
- def call(env, response)
7
- start_once!
8
-
9
- if @queue.size > MAX_QUEUE_SIZE
10
- Umbra.logger.warn '[umbra] Publish queue at max - dropping items'
11
- return
12
- end
13
-
14
- @queue.push(proc { super(env, response) })
15
- end
16
-
17
- private
18
-
19
- # rubocop:disable Metrics/MethodLength
20
- def start_once!
21
- LOCK.synchronize do
22
- return if @started == Process.pid
23
-
24
- Umbra.logger.info '[umbra] Starting publishing thread'
25
-
26
- @started = Process.pid
27
- @queue = Queue.new
2
+ class Publisher
3
+ DEFAULT_MAX_QUEUE = 100
4
+ DEFAULT_MIN_THREADS = 1
5
+ DEFAULT_MAX_THREADS = 1
6
+
7
+ def initialize(**options)
8
+ @pool = Concurrent::CachedThreadPool.new(
9
+ min_threads: options.fetch(:min_threads, DEFAULT_MIN_THREADS),
10
+ max_threads: options.fetch(:max_thread, DEFAULT_MAX_THREADS),
11
+ max_queue: options.fetch(:max_queue, DEFAULT_MAX_QUEUE),
12
+ fallback_policy: :abort
13
+ )
14
+ end
28
15
 
29
- worker_thread = Thread.new do
30
- while (x = @queue.pop)
31
- break if x == STOP
16
+ def call(env, response, encoder: Umbra.encoder, redis: Umbra.redis)
17
+ @pool << proc { call!(env, response, encoder: encoder, redis: redis) }
32
18
 
33
- begin
34
- x.call
35
- rescue StandardError => e
36
- Umbra.logger.warn '[umbra] Error in publishing thread'
37
- Umbra.config.error_handler.call(e)
38
- end
39
- end
40
- end
19
+ true
20
+ rescue Concurrent::RejectedExecutionError
21
+ Umbra.logger.warn '[umbra] Queue at max - dropping items'
41
22
 
42
- at_exit do
43
- @queue.push(STOP)
44
- worker_thread.join
45
- end
46
- end
47
- end
48
- # rubocop:enable Metrics/MethodLength
23
+ false
49
24
  end
50
25
 
51
- STOP = Object.new
52
- LOCK = Mutex.new
53
- private_constant :STOP, :LOCK
26
+ def call!(env, response, encoder: Umbra.encoder, redis: Umbra.redis)
27
+ redis.publish(Umbra::CHANNEL, encoder.call(env, response))
28
+ end
54
29
  end
55
30
  end
@@ -21,9 +21,9 @@ module Umbra
21
21
 
22
22
  def headers(env)
23
23
  request(env)
24
- .fetch('headers')
25
- .merge(UMBRA_HEADERS)
26
- .transform_keys { |key| key.split('_').drop(1).map(&:capitalize).join('-') }
24
+ .fetch('headers')
25
+ .merge(UMBRA_HEADERS)
26
+ .transform_keys { |key| key.split('_').drop(1).map(&:capitalize).join('-') }
27
27
  end
28
28
 
29
29
  def method(env)
@@ -1,60 +1,34 @@
1
1
  module Umbra
2
2
  class ShadowRequester
3
+ attr_reader :queue, :count
4
+
3
5
  def initialize(count: 1, pool: 1, max_queue_size: 100)
4
6
  @count = count
5
- @pool = pool
6
- @queue = Queue.new
7
- @stop = Object.new
8
- @lock = Mutex.new
9
- @max_queue_size = max_queue_size
7
+ @queue ||= Concurrent::CachedThreadPool.new(
8
+ min_threads: 1,
9
+ max_threads: pool,
10
+ max_queue: max_queue_size,
11
+ fallback_policy: :abort
12
+ )
10
13
  end
11
14
 
12
15
  def call(env)
13
- start_worker!
14
-
15
- if @queue.size > @max_queue_size
16
- Umbra.logger.warn '[umbra] Shadowing queue at max - dropping items'
17
- return
18
- end
16
+ queue << proc { call!(env) }
19
17
 
20
- request = RequestBuilder.call(env)
18
+ true
19
+ rescue Concurrent::RejectedExecutionError
20
+ Umbra.logger.warn '[umbra] Shadowing queue at max - dropping items'
21
21
 
22
- @count.times { @queue.push(request) }
22
+ false
23
23
  end
24
24
 
25
- private
26
-
27
- # rubocop:disable Metrics/MethodLength
28
- def start_worker!
29
- @lock.synchronize do
30
- return if @started
31
-
32
- @started = true
33
- Umbra.logger.info '[umbra] Starting shadowing threads...'
34
-
35
- workers = (0...@pool).map do |thread_num|
36
- Thread.new do
37
- Umbra.logger.info "[umbra] shadow thread #{thread_num} waiting"
38
-
39
- while (request = @queue.pop)
40
- break if request == @stop
25
+ def call!(env)
26
+ hydra = Typhoeus::Hydra.new
27
+ request = RequestBuilder.call(env)
41
28
 
42
- begin
43
- request.run
44
- rescue StandardError => e
45
- Umbra.logger.warn "[umbra] error in shadow thread #{thread_num}"
46
- Umbra.config.error_handler.call(e)
47
- end
48
- end
49
- end
50
- end
29
+ @count.times { hydra.queue(request) }
51
30
 
52
- at_exit do
53
- @pool.times { @queue.push(@stop) }
54
- workers.map(&:join)
55
- end
56
- end
31
+ hydra.run
57
32
  end
58
- # rubocop:enable Metrics/MethodLength
59
33
  end
60
34
  end
data/lib/umbra/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Umbra
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0.pre'
5
5
  end
data/umbra-rb.gemspec CHANGED
@@ -28,9 +28,12 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency 'bundler', '~> 2.0'
29
29
  spec.add_development_dependency 'carwow_rubocop'
30
30
  spec.add_development_dependency 'pry'
31
- spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rack'
32
+ spec.add_development_dependency 'rake', '~> 13.0'
32
33
  spec.add_development_dependency 'rspec', '~> 3.0'
34
+ spec.add_development_dependency 'webmock', '~> 3'
33
35
 
36
+ spec.add_dependency 'concurrent-ruby', '~> 1.1'
34
37
  spec.add_dependency 'multi_json', '~> 1.13'
35
38
  spec.add_dependency 'oj', '~> 3.9'
36
39
  spec.add_dependency 'redis', '~> 4.1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: umbra-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - carwow Developers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-07 00:00:00.000000000 Z
11
+ date: 2020-01-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '10.0'
75
+ version: '13.0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '10.0'
82
+ version: '13.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,34 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: concurrent-ruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.1'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.1'
83
125
  - !ruby/object:Gem::Dependency
84
126
  name: multi_json
85
127
  requirement: !ruby/object:Gem::Requirement
@@ -152,6 +194,7 @@ files:
152
194
  - LICENSE.txt
153
195
  - README.md
154
196
  - Rakefile
197
+ - config.ru
155
198
  - lib/umbra.rb
156
199
  - lib/umbra/config.rb
157
200
  - lib/umbra/encoder.rb
@@ -160,7 +203,6 @@ files:
160
203
  - lib/umbra/request_builder.rb
161
204
  - lib/umbra/shadow_requester.rb
162
205
  - lib/umbra/subscriber.rb
163
- - lib/umbra/synchronous_publisher.rb
164
206
  - lib/umbra/version.rb
165
207
  - umbra-rb.gemspec
166
208
  homepage: https://github.com/carwow/umbra
@@ -181,9 +223,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
181
223
  version: '0'
182
224
  required_rubygems_version: !ruby/object:Gem::Requirement
183
225
  requirements:
184
- - - ">="
226
+ - - ">"
185
227
  - !ruby/object:Gem::Version
186
- version: '0'
228
+ version: 1.3.1
187
229
  requirements: []
188
230
  rubygems_version: 3.0.3
189
231
  signing_key:
@@ -1,7 +0,0 @@
1
- module Umbra
2
- class SynchronousPublisher
3
- def self.call(env, response, encoder: Umbra.encoder, redis: Umbra.redis)
4
- redis.publish(Umbra::CHANNEL, encoder.call(env, response))
5
- end
6
- end
7
- end