sneakers 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 562f562a5bb003fdf3d00ae2a37eaf8e3201f80c
4
- data.tar.gz: 922e09184bfd33fd91aac65f3ca109a98f85ad46
3
+ metadata.gz: 3e5b3a5d3740de3c7404234fad5dfe7286d8684a
4
+ data.tar.gz: fce6b1c8aedb2f0755a16be3d493205badb985a2
5
5
  SHA512:
6
- metadata.gz: 5261d1b94c18d35bd051313865eec1612a74cfa1b4b5d340f942eec951f3f8fc0cf1f5f169c47ac48a57ef9bbd5aee62baffcdef8eb18741542fe64ce1beaa14
7
- data.tar.gz: fbcb6831ef3fa9f5fd28a6ac12c1ef8a83e12aed46e0834a128fc43e752c6bc7f435dfc51fa5cd3307b168ca7b130bc6be0dd702738ceda8e00390d8488e9cf7
6
+ metadata.gz: b4f462c76d5c6a36bf1d8b2731b1329461f529c12a77604ad9e2cb5f526832ffcfc94aed16239bade4b18f89626c40fd5469e4d2295b97d38bc6df130e87c828
7
+ data.tar.gz: 7fd337c1fd808b6c1ec19e186b0a70879ee10f8fbb7a81ae5527a9ba5df4434468ce8a90a3532a7de0f0a6970b105a9b79aa128ccc3d9c2b04d0fa8fe376db20
@@ -1,11 +1,15 @@
1
- env:
2
- - INTEGRATION_LOG=1 INTEGRATION=1
3
1
  services:
4
2
  - rabbitmq
5
3
  - redis-server
6
4
  language: ruby
7
5
  rvm:
6
+ - ruby-head
8
7
  - 2.2
9
8
  - 2.1
10
9
  - 2.0.0
10
+ matrix:
11
+ include:
12
+ - rvm: 2.2
13
+ env: INTEGRATION_LOG=1 INTEGRATION=1
14
+
11
15
 
@@ -4,7 +4,8 @@ require 'sneakers'
4
4
  class BenchmarkWorker
5
5
  include Sneakers::Worker
6
6
  from_queue 'downloads',
7
- :durable => false,
7
+ exchange_options: { durable: false },
8
+ queue_options: { durable: false },
8
9
  :ack => true,
9
10
  :threads => 50,
10
11
  :prefetch => 50,
@@ -9,9 +9,8 @@ Sneakers.configure(:handler => Sneakers::Handlers::Maxretry,
9
9
  :threads => 1,
10
10
  :prefetch => 1,
11
11
  :exchange => 'sneakers',
12
- :exchange_type => 'topic',
13
- :routing_key => ['#', 'something'],
14
- :durable => true,
12
+ :exchange_options => { :type => 'topic', durable: true },
13
+ :routing_key => ['#', 'something']
15
14
  )
16
15
  Sneakers.logger.level = Logger::DEBUG
17
16
 
@@ -4,7 +4,8 @@ require 'sneakers'
4
4
  class WorkflowWorker
5
5
  include Sneakers::Worker
6
6
  from_queue 'downloads',
7
- :durable => false,
7
+ exchange_options: { durable: false },
8
+ queue_options: { durable: false },
8
9
  :ack => true,
9
10
  :threads => 50,
10
11
  :prefetch => 50,
@@ -20,5 +21,3 @@ class WorkflowWorker
20
21
  ack!
21
22
  end
22
23
  end
23
-
24
-
@@ -27,7 +27,6 @@ module Sneakers
27
27
  def configure(opts={})
28
28
  # worker > userland > defaults
29
29
  CONFIG.merge!(opts)
30
-
31
30
  setup_general_logger!
32
31
  setup_worker_concerns!
33
32
  setup_general_publisher!
@@ -6,6 +6,20 @@ module Sneakers
6
6
  extend Forwardable
7
7
  def_delegators :@hash, :to_hash, :[], :[]=, :==, :fetch, :delete, :has_key?
8
8
 
9
+ EXCHANGE_OPTION_DEFAULTS = {
10
+ :type => :direct,
11
+ :durable => true,
12
+ :auto_delete => false,
13
+ :arguments => {} # Passed as :arguments to Bunny::Channel#exchange
14
+ }.freeze
15
+
16
+ QUEUE_OPTION_DEFAULTS = {
17
+ :durable => true,
18
+ :auto_delete => false,
19
+ :exclusive => false,
20
+ :arguments => {}
21
+ }.freeze
22
+
9
23
  DEFAULTS = {
10
24
  # runner
11
25
  :runner_config_file => nil,
@@ -22,13 +36,12 @@ module Sneakers
22
36
  :prefetch => 10,
23
37
  :threads => 10,
24
38
  :share_threads => false,
25
- :durable => true,
26
39
  :ack => true,
27
40
  :heartbeat => 2,
41
+ :hooks => {},
28
42
  :exchange => 'sneakers',
29
- :exchange_type => :direct,
30
- :exchange_arguments => {}, # Passed as :arguments to Bunny::Channel#exchange
31
- :hooks => {}
43
+ :exchange_options => EXCHANGE_OPTION_DEFAULTS,
44
+ :queue_options => QUEUE_OPTION_DEFAULTS
32
45
  }.freeze
33
46
 
34
47
 
@@ -44,6 +57,9 @@ module Sneakers
44
57
 
45
58
  def merge!(hash)
46
59
  hash = hash.dup
60
+ hash = map_deprecated_exchange_options_key(hash, :exchange_type, :type)
61
+ hash = map_deprecated_exchange_options_key(hash, :exchange_arguments, :arguments)
62
+ hash = map_deprecated_exchange_options_key(hash, :durable, :durable)
47
63
 
48
64
  # parse vhost from amqp if vhost is not specified explicitly, only
49
65
  # if we're not given a connection to use.
@@ -62,7 +78,7 @@ module Sneakers
62
78
  end
63
79
  end
64
80
 
65
- @hash.merge!(hash)
81
+ @hash = deep_merge(@hash, hash)
66
82
  end
67
83
 
68
84
  def merge(hash)
@@ -82,5 +98,18 @@ module Sneakers
82
98
  end
83
99
  alias_method :inspect_without_redaction, :inspect
84
100
  alias_method :inspect, :inspect_with_redaction
101
+
102
+ def map_deprecated_exchange_options_key(hash = {}, deprecated_key, key)
103
+ return hash if hash[deprecated_key].nil?
104
+ hash = deep_merge({ exchange_options: { key => hash[deprecated_key] } }, hash)
105
+ hash = deep_merge({ queue_options: { key => hash[deprecated_key] } }, hash) if deprecated_key == :durable
106
+ hash.delete(deprecated_key)
107
+ hash
108
+ end
109
+
110
+ def deep_merge(first, second)
111
+ merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
112
+ first.merge(second, &merger)
113
+ end
85
114
  end
86
115
  end
@@ -20,15 +20,22 @@ module Sneakers
20
20
 
21
21
  private
22
22
  def ensure_connection!
23
- @bunny = Bunny.new(@opts[:amqp], heartbeat: @opts[:heartbeat], vhost: @opts[:vhost], :logger => Sneakers::logger)
23
+ # If we've already got a bunny object, use it. This allows people to
24
+ # specify all kinds of options we don't need to know about (e.g. for ssl).
25
+ @bunny = @opts[:connection]
26
+ @bunny ||= create_bunny_connection
24
27
  @bunny.start
25
28
  @channel = @bunny.create_channel
26
- @exchange = @channel.exchange(@opts[:exchange], type: @opts[:exchange_type], durable: @opts[:durable], arguments: @opts[:exchange_arguments])
29
+ @exchange = @channel.exchange(@opts[:exchange], @opts[:exchange_options])
27
30
  end
28
31
 
29
32
  def connected?
30
33
  @bunny && @bunny.connected?
31
34
  end
35
+
36
+ def create_bunny_connection
37
+ Bunny.new(@opts[:amqp], :vhost => @opts[:vhost], :heartbeat => @opts[:heartbeat], :logger => Sneakers::logger)
38
+ end
32
39
  end
33
40
  end
34
41
 
@@ -26,10 +26,7 @@ class Sneakers::Queue
26
26
  @channel.prefetch(@opts[:prefetch])
27
27
 
28
28
  exchange_name = @opts[:exchange]
29
- @exchange = @channel.exchange(exchange_name,
30
- :type => @opts[:exchange_type],
31
- :durable => @opts[:durable],
32
- :arguments => @opts[:exchange_arguments])
29
+ @exchange = @channel.exchange(exchange_name, @opts[:exchange_options])
33
30
 
34
31
  routing_key = @opts[:routing_key] || @name
35
32
  routing_keys = [*routing_key]
@@ -37,8 +34,7 @@ class Sneakers::Queue
37
34
  # TODO: get the arguments from the handler? Retry handler wants this so you
38
35
  # don't have to line up the queue's dead letter argument with the exchange
39
36
  # you'll create for retry.
40
- queue_durable = @opts[:queue_durable].nil? ? @opts[:durable] : @opts[:queue_durable]
41
- queue = @channel.queue(@name, :durable => queue_durable, :arguments => @opts[:arguments])
37
+ queue = @channel.queue(@name, @opts[:queue_options])
42
38
 
43
39
  if exchange_name.length > 0
44
40
  routing_keys.each do |key|
@@ -1,3 +1,3 @@
1
1
  module Sneakers
2
- VERSION = "2.2.1"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -2,6 +2,19 @@ require 'spec_helper'
2
2
  require 'sneakers'
3
3
 
4
4
  describe Sneakers::Publisher do
5
+ let :pub_vars do
6
+ {
7
+ :prefetch => 25,
8
+ :durable => true,
9
+ :ack => true,
10
+ :heartbeat => 2,
11
+ :vhost => '/',
12
+ :exchange => "sneakers",
13
+ :exchange_type => :direct,
14
+ :exchange_arguments => { 'x-arg' => 'value' }
15
+ }
16
+ end
17
+
5
18
  describe '#publish' do
6
19
  before do
7
20
  Sneakers.clear!
@@ -58,14 +71,14 @@ describe Sneakers::Publisher do
58
71
  logger = Logger.new('/dev/null')
59
72
  Sneakers.configure(
60
73
  amqp: 'amqp://someuser:somepassword@somehost:5672',
61
- heartbeat: 1, exchange: 'another_exchange',
62
- exchange_type: :topic,
63
- exchange_arguments: { 'x-arg' => 'value' },
74
+ heartbeat: 1,
75
+ exchange: 'another_exchange',
76
+ exchange_options: { :type => :topic, :arguments => { 'x-arg' => 'value' } },
64
77
  log: logger,
65
78
  durable: false)
66
79
 
67
80
  channel = Object.new
68
- mock(channel).exchange('another_exchange', type: :topic, durable: false, arguments: { 'x-arg' => 'value' }) do
81
+ mock(channel).exchange('another_exchange', type: :topic, durable: false, :auto_delete => false, arguments: { 'x-arg' => 'value' }) do
69
82
  mock(Object.new).publish('test msg', routing_key: 'downloads')
70
83
  end
71
84
 
@@ -78,7 +91,36 @@ describe Sneakers::Publisher do
78
91
  p = Sneakers::Publisher.new
79
92
 
80
93
  p.publish('test msg', to_queue: 'downloads')
94
+ end
95
+
96
+ it 'should use an externally instantiated bunny session if provided' do
97
+ logger = Logger.new('/dev/null')
98
+ channel = Object.new
99
+ exchange = Object.new
100
+ existing_session = Bunny.new
101
+ my_vars = pub_vars.merge(to_queue: 'downloads')
102
+
103
+ mock(existing_session).start
104
+ mock(existing_session).create_channel { channel }
81
105
 
106
+ mock(channel).exchange('another_exchange', type: :topic, durable: false, :auto_delete => false, arguments: { 'x-arg' => 'value' }) do
107
+ exchange
108
+ end
109
+
110
+ mock(exchange).publish('test msg', my_vars)
111
+
112
+ Sneakers.configure(
113
+ connection: existing_session,
114
+ heartbeat: 1, exchange: 'another_exchange',
115
+ exchange_type: :topic,
116
+ exchange_arguments: { 'x-arg' => 'value' },
117
+ log: logger,
118
+ durable: false
119
+ )
120
+
121
+ p = Sneakers::Publisher.new
122
+ p.publish('test msg', my_vars)
123
+ p.instance_variable_get(:@bunny).must_equal existing_session
82
124
  end
83
125
  end
84
126
  end
@@ -5,13 +5,18 @@ describe Sneakers::Queue do
5
5
  let :queue_vars do
6
6
  {
7
7
  :prefetch => 25,
8
- :durable => true,
9
8
  :ack => true,
10
9
  :heartbeat => 2,
11
10
  :vhost => '/',
12
11
  :exchange => "sneakers",
13
- :exchange_type => :direct,
14
- :exchange_arguments => { 'x-arg' => 'value' }
12
+ :exchange_options => {
13
+ :type => :direct,
14
+ durable: true,
15
+ :arguments => { 'x-arg' => 'value' }
16
+ },
17
+ queue_options: {
18
+ durable: true
19
+ }
15
20
  }
16
21
  end
17
22
 
@@ -81,7 +86,7 @@ describe Sneakers::Queue do
81
86
 
82
87
  it "creates a non-durable queue if :queue_durable => false" do
83
88
  mock(@mkchan).queue("test_nondurable", :durable => false) { @mkqueue_nondurable }
84
- queue_vars[:queue_durable] = false
89
+ queue_vars[:queue_options][:durable] = false
85
90
  q = Sneakers::Queue.new("test_nondurable", queue_vars)
86
91
 
87
92
  mock(@mkqueue_nondurable).bind(@mkex, :routing_key => "test_nondurable")
@@ -144,4 +149,3 @@ describe Sneakers::Queue do
144
149
  end
145
150
  end
146
151
  end
147
-
@@ -6,7 +6,18 @@ require 'timeout'
6
6
  class DummyWorker
7
7
  include Sneakers::Worker
8
8
  from_queue 'downloads',
9
- :durable => false,
9
+ :exchange_options => {
10
+ :type => :topic,
11
+ :durable => false,
12
+ :auto_delete => true,
13
+ :arguments => { 'x-arg' => 'value' }
14
+ },
15
+ :queue_options => {
16
+ :durable => false,
17
+ :auto_delete => true,
18
+ :exclusive => true,
19
+ :arguments => { 'x-arg' => 'value' }
20
+ },
10
21
  :ack => false,
11
22
  :threads => 50,
12
23
  :prefetch => 40,
@@ -101,6 +112,16 @@ class WithParamsWorker
101
112
  end
102
113
  end
103
114
 
115
+ class WithDeprecatedExchangeOptionsWorker
116
+ include Sneakers::Worker
117
+ from_queue 'defaults',
118
+ :durable => false,
119
+ :exchange_type => :topic,
120
+ :exchange_arguments => { 'x-arg' => 'value' }
121
+
122
+ def work(msg)
123
+ end
124
+ end
104
125
 
105
126
  class TestPool
106
127
  def process(*args,&block)
@@ -153,12 +174,8 @@ describe Sneakers::Worker do
153
174
 
154
175
  describe "#initialize" do
155
176
  describe "builds an internal queue" do
156
- before do
157
- @dummy_q = DummyWorker.new.queue
158
- @defaults_q = DefaultsWorker.new.queue
159
- end
160
-
161
177
  it "should build a queue with correct configuration given defaults" do
178
+ @defaults_q = DefaultsWorker.new.queue
162
179
  @defaults_q.name.must_equal('defaults')
163
180
  @defaults_q.opts.to_hash.must_equal(
164
181
  :runner_config_file => nil,
@@ -172,13 +189,22 @@ describe Sneakers::Worker do
172
189
  :prefetch => 10,
173
190
  :threads => 10,
174
191
  :share_threads => false,
175
- :durable => true,
176
192
  :ack => true,
177
193
  :amqp => "amqp://guest:guest@localhost:5672",
178
194
  :vhost => "/",
179
195
  :exchange => "sneakers",
180
- :exchange_type => :direct,
181
- :exchange_arguments => {},
196
+ :exchange_options => {
197
+ :type => :direct,
198
+ :durable => true,
199
+ :auto_delete => false,
200
+ :arguments => {}
201
+ },
202
+ :queue_options => {
203
+ :durable => true,
204
+ :auto_delete => false,
205
+ :exclusive => false,
206
+ :arguments => {}
207
+ },
182
208
  :hooks => {},
183
209
  :handler => Sneakers::Handlers::Oneshot,
184
210
  :heartbeat => 2,
@@ -187,6 +213,7 @@ describe Sneakers::Worker do
187
213
  end
188
214
 
189
215
  it "should build a queue with given configuration" do
216
+ @dummy_q = DummyWorker.new.queue
190
217
  @dummy_q.name.must_equal('downloads')
191
218
  @dummy_q.opts.to_hash.must_equal(
192
219
  :runner_config_file => nil,
@@ -200,19 +227,66 @@ describe Sneakers::Worker do
200
227
  :prefetch => 40,
201
228
  :threads => 50,
202
229
  :share_threads => false,
203
- :durable => false,
204
230
  :ack => false,
205
231
  :amqp => "amqp://guest:guest@localhost:5672",
206
232
  :vhost => "/",
207
233
  :exchange => "dummy",
208
- :exchange_type => :direct,
209
- :exchange_arguments => {},
234
+ :exchange_options => {
235
+ :type => :topic,
236
+ :durable => false,
237
+ :auto_delete => true,
238
+ :arguments => { 'x-arg' => 'value' }
239
+ },
240
+ :queue_options => {
241
+ :durable => false,
242
+ :auto_delete => true,
243
+ :exclusive => true,
244
+ :arguments => { 'x-arg' => 'value' }
245
+ },
210
246
  :hooks => {},
211
247
  :handler => Sneakers::Handlers::Oneshot,
212
248
  :heartbeat => 5,
213
249
  :amqp_heartbeat => 10
214
250
  )
215
251
  end
252
+
253
+ it "should build a queue with correct configuration given deprecated exchange options" do
254
+ @deprecated_exchange_opts_q = WithDeprecatedExchangeOptionsWorker.new.queue
255
+ @deprecated_exchange_opts_q.name.must_equal('defaults')
256
+ @deprecated_exchange_opts_q.opts.to_hash.must_equal(
257
+ :runner_config_file => nil,
258
+ :metrics => nil,
259
+ :daemonize => true,
260
+ :start_worker_delay => 0.2,
261
+ :workers => 4,
262
+ :log => "sneakers.log",
263
+ :pid_path => "sneakers.pid",
264
+ :timeout_job_after => 5,
265
+ :prefetch => 10,
266
+ :threads => 10,
267
+ :share_threads => false,
268
+ :ack => true,
269
+ :amqp => "amqp://guest:guest@localhost:5672",
270
+ :vhost => "/",
271
+ :exchange => "sneakers",
272
+ :exchange_options => {
273
+ :type => :topic,
274
+ :durable => false,
275
+ :auto_delete => false,
276
+ :arguments => { 'x-arg' => 'value' }
277
+ },
278
+ :queue_options => {
279
+ :durable => false,
280
+ :auto_delete => false,
281
+ :exclusive => false,
282
+ :arguments => {}
283
+ },
284
+ :hooks => {},
285
+ :handler => Sneakers::Handlers::Oneshot,
286
+ :heartbeat => 2,
287
+ :amqp_heartbeat => 10
288
+ )
289
+ end
216
290
  end
217
291
 
218
292
  describe "initializes worker" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sneakers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dotan Nahum
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-29 00:00:00.000000000 Z
11
+ date: 2015-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: serverengine