sneakers 0.1.1.pre → 1.0.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 +7 -0
- data/.gitignore +3 -0
- data/LICENSE.txt +2 -2
- data/Rakefile +1 -0
- data/examples/max_retry_handler.rb +78 -0
- data/examples/newrelic_metrics_worker.rb +40 -0
- data/lib/sneakers/cli.rb +3 -3
- data/lib/sneakers/concerns/logging.rb +1 -1
- data/lib/sneakers/configuration.rb +47 -0
- data/lib/sneakers/handlers/maxretry.rb +183 -0
- data/lib/sneakers/handlers/oneshot.rb +11 -10
- data/lib/sneakers/publisher.rb +11 -10
- data/lib/sneakers/queue.rb +16 -7
- data/lib/sneakers/runner.rb +4 -4
- data/lib/sneakers/version.rb +1 -1
- data/lib/sneakers/worker.rb +38 -19
- data/lib/sneakers/workergroup.rb +2 -2
- data/lib/sneakers.rb +23 -48
- data/sneakers.gemspec +22 -22
- data/spec/sneakers/concerns/{logging.rb → logging_spec.rb} +1 -1
- data/spec/sneakers/concerns/{metrics.rb → metrics_spec.rb} +0 -0
- data/spec/sneakers/configuration_spec.rb +42 -0
- data/spec/sneakers/publisher_spec.rb +46 -22
- data/spec/sneakers/queue_spec.rb +32 -4
- data/spec/sneakers/sneakers_spec.rb +7 -6
- data/spec/sneakers/worker_handlers_spec.rb +350 -0
- data/spec/sneakers/worker_spec.rb +85 -48
- data/spec/spec_helper.rb +3 -1
- metadata +46 -64
data/lib/sneakers/worker.rb
CHANGED
@@ -4,17 +4,17 @@ require 'timeout'
|
|
4
4
|
|
5
5
|
module Sneakers
|
6
6
|
module Worker
|
7
|
-
attr_reader :queue, :id
|
7
|
+
attr_reader :queue, :id, :opts
|
8
8
|
|
9
9
|
# For now, a worker is hardly dependant on these concerns
|
10
10
|
# (because it uses methods from them directly.)
|
11
11
|
include Concerns::Logging
|
12
12
|
include Concerns::Metrics
|
13
13
|
|
14
|
-
def initialize(queue=nil, pool=nil, opts=
|
15
|
-
opts = self.class.queue_opts
|
14
|
+
def initialize(queue = nil, pool = nil, opts = {})
|
15
|
+
opts = opts.merge(self.class.queue_opts || {})
|
16
16
|
queue_name = self.class.queue_name
|
17
|
-
opts = Sneakers::
|
17
|
+
opts = Sneakers::CONFIG.merge(opts)
|
18
18
|
|
19
19
|
@should_ack = opts[:ack]
|
20
20
|
@timeout_after = opts[:timeout_job_after]
|
@@ -34,12 +34,14 @@ module Sneakers
|
|
34
34
|
def reject!; :reject; end
|
35
35
|
def requeue!; :requeue; end
|
36
36
|
|
37
|
-
def publish(msg,
|
38
|
-
|
39
|
-
|
37
|
+
def publish(msg, opts)
|
38
|
+
to_queue = opts.delete(:to_queue)
|
39
|
+
opts[:routing_key] ||= to_queue
|
40
|
+
return unless opts[:routing_key]
|
41
|
+
@queue.exchange.publish(msg, opts)
|
40
42
|
end
|
41
43
|
|
42
|
-
def do_work(
|
44
|
+
def do_work(delivery_info, metadata, msg, handler)
|
43
45
|
worker_trace "Working off: #{msg}"
|
44
46
|
|
45
47
|
@pool.process do
|
@@ -51,7 +53,7 @@ module Sneakers
|
|
51
53
|
Timeout.timeout(@timeout_after) do
|
52
54
|
metrics.timing("work.#{self.class.name}.time") do
|
53
55
|
if @call_with_params
|
54
|
-
res = work_with_params(msg,
|
56
|
+
res = work_with_params(msg, delivery_info, metadata)
|
55
57
|
else
|
56
58
|
res = work(msg)
|
57
59
|
end
|
@@ -59,29 +61,30 @@ module Sneakers
|
|
59
61
|
end
|
60
62
|
rescue Timeout::Error
|
61
63
|
res = :timeout
|
62
|
-
|
64
|
+
worker_error('timeout')
|
63
65
|
rescue => ex
|
64
66
|
res = :error
|
65
67
|
error = ex
|
66
|
-
|
68
|
+
worker_error('unexpected error', ex)
|
67
69
|
end
|
68
70
|
|
69
71
|
if @should_ack
|
72
|
+
|
70
73
|
if res == :ack
|
71
74
|
# note to future-self. never acknowledge multiple (multiple=true) messages under threads.
|
72
|
-
handler.acknowledge(
|
75
|
+
handler.acknowledge(delivery_info, metadata, msg)
|
73
76
|
elsif res == :timeout
|
74
|
-
handler.timeout(
|
77
|
+
handler.timeout(delivery_info, metadata, msg)
|
75
78
|
elsif res == :error
|
76
|
-
handler.error(
|
79
|
+
handler.error(delivery_info, metadata, msg, error)
|
77
80
|
elsif res == :reject
|
78
|
-
handler.reject(
|
81
|
+
handler.reject(delivery_info, metadata, msg)
|
79
82
|
elsif res == :requeue
|
80
|
-
handler.reject(
|
83
|
+
handler.reject(delivery_info, metadata, msg, true)
|
81
84
|
else
|
82
|
-
handler.noop(
|
85
|
+
handler.noop(delivery_info, metadata, msg)
|
83
86
|
end
|
84
|
-
metrics.increment("work.#{self.class.name}.handled.#{res || '
|
87
|
+
metrics.increment("work.#{self.class.name}.handled.#{res || 'noop'}")
|
85
88
|
end
|
86
89
|
|
87
90
|
metrics.increment("work.#{self.class.name}.ended")
|
@@ -100,8 +103,24 @@ module Sneakers
|
|
100
103
|
worker_trace "New worker: I'm alive."
|
101
104
|
end
|
102
105
|
|
106
|
+
# Construct a log message with some standard prefix for this worker
|
107
|
+
def log_msg(msg)
|
108
|
+
"[#{@id}][#{Thread.current}][#{@queue.name}][#{@queue.opts}] #{msg}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Helper to log an error message with an optional exception
|
112
|
+
def worker_error(msg, exception = nil)
|
113
|
+
s = log_msg(msg)
|
114
|
+
if exception
|
115
|
+
s += " [Exception error=#{exception.message.inspect} error_class=#{exception.class}"
|
116
|
+
s += " backtrace=#{exception.backtrace.take(50).join(',')}" unless exception.backtrace.nil?
|
117
|
+
s += "]"
|
118
|
+
end
|
119
|
+
logger.error(s)
|
120
|
+
end
|
121
|
+
|
103
122
|
def worker_trace(msg)
|
104
|
-
logger.debug
|
123
|
+
logger.debug(log_msg(msg))
|
105
124
|
end
|
106
125
|
|
107
126
|
def self.included(base)
|
data/lib/sneakers/workergroup.rb
CHANGED
@@ -7,12 +7,12 @@ module Sneakers
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def before_fork
|
10
|
-
fbefore = Sneakers::
|
10
|
+
fbefore = Sneakers::CONFIG[:hooks][:before_fork]
|
11
11
|
fbefore.call if fbefore
|
12
12
|
end
|
13
13
|
|
14
14
|
def after_fork # note! this is not Serverengine#after_start, this is ours!
|
15
|
-
fafter = Sneakers::
|
15
|
+
fafter = Sneakers::CONFIG[:hooks][:after_fork]
|
16
16
|
fafter.call if fafter
|
17
17
|
end
|
18
18
|
|
data/lib/sneakers.rb
CHANGED
@@ -3,7 +3,6 @@ require 'thread/pool'
|
|
3
3
|
require 'bunny'
|
4
4
|
require 'logger'
|
5
5
|
|
6
|
-
|
7
6
|
module Sneakers
|
8
7
|
module Handlers
|
9
8
|
end
|
@@ -11,6 +10,7 @@ module Sneakers
|
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
13
|
+
require 'sneakers/configuration'
|
14
14
|
require 'sneakers/support/production_formatter'
|
15
15
|
require 'sneakers/concerns/logging'
|
16
16
|
require 'sneakers/concerns/metrics'
|
@@ -19,36 +19,13 @@ require 'sneakers/worker'
|
|
19
19
|
require 'sneakers/publisher'
|
20
20
|
|
21
21
|
module Sneakers
|
22
|
+
extend self
|
23
|
+
|
24
|
+
CONFIG = Configuration.new
|
22
25
|
|
23
|
-
|
24
|
-
# runner
|
25
|
-
:runner_config_file => nil,
|
26
|
-
:metrics => nil,
|
27
|
-
:daemonize => false,
|
28
|
-
:start_worker_delay => 0.2,
|
29
|
-
:workers => 4,
|
30
|
-
:log => STDOUT,
|
31
|
-
:pid_path => 'sneakers.pid',
|
32
|
-
|
33
|
-
#workers
|
34
|
-
:timeout_job_after => 5,
|
35
|
-
:prefetch => 10,
|
36
|
-
:threads => 10,
|
37
|
-
:durable => true,
|
38
|
-
:ack => true,
|
39
|
-
:heartbeat => 2,
|
40
|
-
:amqp => 'amqp://guest:guest@localhost:5672',
|
41
|
-
:vhost => '/',
|
42
|
-
:exchange => 'sneakers',
|
43
|
-
:exchange_type => :direct,
|
44
|
-
:hooks => {}
|
45
|
-
}.freeze
|
46
|
-
|
47
|
-
Config = DEFAULTS.dup
|
48
|
-
|
49
|
-
def self.configure(opts={})
|
26
|
+
def configure(opts={})
|
50
27
|
# worker > userland > defaults
|
51
|
-
|
28
|
+
CONFIG.merge!(opts)
|
52
29
|
|
53
30
|
setup_general_logger!
|
54
31
|
setup_worker_concerns!
|
@@ -56,52 +33,50 @@ module Sneakers
|
|
56
33
|
@configured = true
|
57
34
|
end
|
58
35
|
|
59
|
-
def
|
60
|
-
|
61
|
-
Config.merge!(DEFAULTS.dup)
|
36
|
+
def clear!
|
37
|
+
CONFIG.clear
|
62
38
|
@logger = nil
|
63
39
|
@publisher = nil
|
64
40
|
@configured = false
|
65
41
|
end
|
66
42
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
43
|
+
def daemonize!(loglevel=Logger::INFO)
|
44
|
+
CONFIG[:log] = 'sneakers.log'
|
45
|
+
CONFIG[:daemonize] = true
|
70
46
|
setup_general_logger!
|
71
47
|
logger.level = loglevel
|
72
48
|
end
|
73
49
|
|
74
|
-
def
|
50
|
+
def logger
|
75
51
|
@logger
|
76
52
|
end
|
77
53
|
|
78
|
-
def
|
54
|
+
def publish(msg, routing)
|
79
55
|
@publisher.publish(msg, routing)
|
80
56
|
end
|
81
57
|
|
82
|
-
def
|
58
|
+
def configured?
|
83
59
|
@configured
|
84
60
|
end
|
85
61
|
|
62
|
+
private
|
86
63
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
if [:info, :debug, :error, :warn].all?{ |meth| Config[:log].respond_to?(meth) }
|
91
|
-
@logger = Config[:log]
|
64
|
+
def setup_general_logger!
|
65
|
+
if [:info, :debug, :error, :warn].all?{ |meth| CONFIG[:log].respond_to?(meth) }
|
66
|
+
@logger = CONFIG[:log]
|
92
67
|
else
|
93
|
-
@logger = Logger.new(
|
68
|
+
@logger = Logger.new(CONFIG[:log])
|
94
69
|
@logger.formatter = Sneakers::Support::ProductionFormatter
|
95
70
|
end
|
96
71
|
end
|
97
72
|
|
98
|
-
def
|
73
|
+
def setup_worker_concerns!
|
99
74
|
Worker.configure_logger(Sneakers::logger)
|
100
|
-
Worker.configure_metrics(
|
101
|
-
|
75
|
+
Worker.configure_metrics(CONFIG[:metrics])
|
76
|
+
CONFIG[:handler] ||= Sneakers::Handlers::Oneshot
|
102
77
|
end
|
103
78
|
|
104
|
-
def
|
79
|
+
def setup_general_publisher!
|
105
80
|
@publisher = Sneakers::Publisher.new
|
106
81
|
end
|
107
82
|
end
|
data/sneakers.gemspec
CHANGED
@@ -4,30 +4,30 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'sneakers/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
7
|
+
gem.name = 'sneakers'
|
8
8
|
gem.version = Sneakers::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
11
|
-
gem.description = %q
|
12
|
-
gem.summary = %q
|
13
|
-
gem.homepage =
|
9
|
+
gem.authors = ['Dotan Nahum']
|
10
|
+
gem.email = ['jondotan@gmail.com']
|
11
|
+
gem.description = %q( Fast background processing framework for Ruby and RabbitMQ )
|
12
|
+
gem.summary = %q( Fast background processing framework for Ruby and RabbitMQ )
|
13
|
+
gem.homepage = ''
|
14
14
|
|
15
|
-
gem.files = `git ls-files`.split($/).reject{|f| f == 'Gemfile.lock'}
|
16
|
-
gem.executables = gem.files.grep(
|
17
|
-
gem.test_files = gem.files.grep(
|
18
|
-
gem.require_paths = [
|
19
|
-
gem.add_dependency
|
20
|
-
gem.add_dependency
|
21
|
-
gem.add_dependency
|
22
|
-
gem.add_dependency
|
15
|
+
gem.files = `git ls-files`.split($/).reject { |f| f == 'Gemfile.lock' }
|
16
|
+
gem.executables = gem.files.grep(/^bin/).map { |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(/^(test|spec|features)\//)
|
18
|
+
gem.require_paths = ['lib']
|
19
|
+
gem.add_dependency 'serverengine'
|
20
|
+
gem.add_dependency 'bunny', '~> 1.1.3'
|
21
|
+
gem.add_dependency 'thread'
|
22
|
+
gem.add_dependency 'thor'
|
23
23
|
|
24
|
-
gem.add_development_dependency
|
25
|
-
gem.add_development_dependency
|
26
|
-
gem.add_development_dependency
|
27
|
-
gem.add_development_dependency
|
28
|
-
gem.add_development_dependency
|
29
|
-
gem.add_development_dependency
|
30
|
-
gem.add_development_dependency
|
31
|
-
gem.add_development_dependency
|
24
|
+
gem.add_development_dependency 'rr'
|
25
|
+
gem.add_development_dependency 'ruby-prof'
|
26
|
+
gem.add_development_dependency 'nokogiri'
|
27
|
+
gem.add_development_dependency 'guard-minitest'
|
28
|
+
gem.add_development_dependency 'metric_fu'
|
29
|
+
gem.add_development_dependency 'simplecov'
|
30
|
+
gem.add_development_dependency 'simplecov-rcov-text'
|
31
|
+
gem.add_development_dependency 'rake'
|
32
32
|
end
|
33
33
|
|
@@ -17,7 +17,7 @@ describe Sneakers::Concerns::Logging do
|
|
17
17
|
Foobar.logger.must_be_nil
|
18
18
|
Foobar.configure_logger
|
19
19
|
Foobar.logger.wont_be_nil
|
20
|
-
Foobar.logger.formatter.must_equal Sneakers::
|
20
|
+
Foobar.logger.formatter.must_equal Sneakers::Support::ProductionFormatter
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should supply accessible instance logger" do
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Sneakers::Configuration do
|
4
|
+
|
5
|
+
it 'should assign a default value for :amqp' do
|
6
|
+
with_env('RABBITMQ_URL', nil) do
|
7
|
+
config = Sneakers::Configuration.new
|
8
|
+
config[:amqp].must_equal 'amqp://guest:guest@localhost:5672'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should assign a default value for :vhost' do
|
13
|
+
with_env('RABBITMQ_URL', nil) do
|
14
|
+
config = Sneakers::Configuration.new
|
15
|
+
config[:vhost].must_equal '/'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should read the value for amqp from RABBITMQ_URL' do
|
20
|
+
url = 'amqp://foo:bar@localhost:5672'
|
21
|
+
with_env('RABBITMQ_URL', url) do
|
22
|
+
config = Sneakers::Configuration.new
|
23
|
+
config[:amqp].must_equal url
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should read the value for vhost from RABBITMQ_URL' do
|
28
|
+
url = 'amqp://foo:bar@localhost:5672/foobarvhost'
|
29
|
+
with_env('RABBITMQ_URL', url) do
|
30
|
+
config = Sneakers::Configuration.new
|
31
|
+
config[:vhost].must_equal 'foobarvhost'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_env(key, value)
|
36
|
+
old_value = ENV[key]
|
37
|
+
ENV[key] = value
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
ENV[key] = old_value
|
41
|
+
end
|
42
|
+
end
|
@@ -1,53 +1,77 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'sneakers'
|
3
3
|
|
4
|
-
|
5
4
|
describe Sneakers::Publisher do
|
6
|
-
describe
|
7
|
-
it
|
5
|
+
describe '#publish' do
|
6
|
+
it 'should publish a message to an exchange' do
|
7
|
+
xchg = Object.new
|
8
|
+
mock(xchg).publish('test msg', routing_key: 'downloads')
|
9
|
+
|
10
|
+
p = Sneakers::Publisher.new
|
11
|
+
p.instance_variable_set(:@exchange, xchg)
|
12
|
+
|
13
|
+
mock(p).ensure_connection! {}
|
14
|
+
p.publish('test msg', to_queue: 'downloads')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should publish with the persistence specified' do
|
8
18
|
xchg = Object.new
|
9
|
-
mock(xchg).publish(
|
19
|
+
mock(xchg).publish('test msg', routing_key: 'downloads', persistence: true)
|
10
20
|
|
11
21
|
p = Sneakers::Publisher.new
|
12
|
-
p.exchange
|
22
|
+
p.instance_variable_set(:@exchange, xchg)
|
13
23
|
|
14
|
-
mock(p).ensure_connection!{}
|
15
|
-
p.publish(
|
24
|
+
mock(p).ensure_connection! {}
|
25
|
+
p.publish('test msg', to_queue: 'downloads', persistence: true)
|
16
26
|
end
|
17
27
|
|
18
|
-
it
|
28
|
+
it 'should publish with arbitrary metadata specified' do
|
19
29
|
xchg = Object.new
|
20
|
-
mock(xchg).publish(
|
30
|
+
mock(xchg).publish('test msg', routing_key: 'downloads', expiration: 1, headers: {foo: 'bar'})
|
21
31
|
|
22
32
|
p = Sneakers::Publisher.new
|
23
|
-
p.exchange
|
24
|
-
|
33
|
+
p.instance_variable_set(:@exchange, xchg)
|
34
|
+
|
35
|
+
mock(p).ensure_connection! {}
|
36
|
+
p.publish('test msg', to_queue: 'downloads', expiration: 1, headers: {foo: 'bar'})
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should not reconnect if already connected' do
|
40
|
+
xchg = Object.new
|
41
|
+
mock(xchg).publish('test msg', routing_key: 'downloads')
|
42
|
+
|
43
|
+
p = Sneakers::Publisher.new
|
44
|
+
p.instance_variable_set(:@exchange, xchg)
|
45
|
+
|
46
|
+
mock(p).connected? { true }
|
25
47
|
mock(p).ensure_connection!.times(0)
|
26
48
|
|
27
|
-
p.publish(
|
49
|
+
p.publish('test msg', to_queue: 'downloads')
|
28
50
|
end
|
29
51
|
|
30
|
-
it
|
52
|
+
it 'should connect to rabbitmq configured on Sneakers.configure' do
|
53
|
+
logger = Logger.new('/dev/null')
|
31
54
|
Sneakers.configure(
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
55
|
+
amqp: 'amqp://someuser:somepassword@somehost:5672',
|
56
|
+
heartbeat: 1, exchange: 'another_exchange',
|
57
|
+
exchange_type: :topic,
|
58
|
+
log: logger,
|
59
|
+
durable: false)
|
36
60
|
|
37
61
|
channel = Object.new
|
38
|
-
mock(channel).exchange(
|
39
|
-
mock(Object.new).publish(
|
40
|
-
|
62
|
+
mock(channel).exchange('another_exchange', type: :topic, durable: false) do
|
63
|
+
mock(Object.new).publish('test msg', routing_key: 'downloads')
|
64
|
+
end
|
41
65
|
|
42
66
|
bunny = Object.new
|
43
67
|
mock(bunny).start
|
44
68
|
mock(bunny).create_channel { channel }
|
45
69
|
|
46
|
-
mock(Bunny).new(
|
70
|
+
mock(Bunny).new('amqp://someuser:somepassword@somehost:5672', heartbeat: 1, vhost: '/', logger: logger) { bunny }
|
47
71
|
|
48
72
|
p = Sneakers::Publisher.new
|
49
73
|
|
50
|
-
p.publish(
|
74
|
+
p.publish('test msg', to_queue: 'downloads')
|
51
75
|
|
52
76
|
end
|
53
77
|
end
|
data/spec/sneakers/queue_spec.rb
CHANGED
@@ -26,6 +26,8 @@ describe Sneakers::Queue do
|
|
26
26
|
@mkchan = Object.new
|
27
27
|
@mkex = Object.new
|
28
28
|
@mkqueue = Object.new
|
29
|
+
@mkqueue_nondurable = Object.new
|
30
|
+
@mkworker = Object.new
|
29
31
|
|
30
32
|
mock(@mkbunny).start {}
|
31
33
|
mock(@mkbunny).create_channel{ @mkchan }
|
@@ -33,19 +35,22 @@ describe Sneakers::Queue do
|
|
33
35
|
|
34
36
|
mock(@mkchan).prefetch(25)
|
35
37
|
mock(@mkchan).exchange("sneakers", :type => :direct, :durable => true){ @mkex }
|
36
|
-
|
38
|
+
|
39
|
+
stub(@mkworker).opts { { :exchange => 'test-exchange' } }
|
37
40
|
end
|
38
41
|
|
39
42
|
it "should setup a bunny queue according to configuration values" do
|
43
|
+
mock(@mkchan).queue("downloads", :durable => true) { @mkqueue }
|
40
44
|
q = Sneakers::Queue.new("downloads", queue_vars)
|
41
45
|
|
42
46
|
mock(@mkqueue).bind(@mkex, :routing_key => "downloads")
|
43
47
|
mock(@mkqueue).subscribe(:block => false, :ack => true)
|
44
48
|
|
45
|
-
q.subscribe(
|
49
|
+
q.subscribe(@mkworker)
|
46
50
|
end
|
47
51
|
|
48
52
|
it "supports multiple routing_keys" do
|
53
|
+
mock(@mkchan).queue("downloads", :durable => true) { @mkqueue }
|
49
54
|
q = Sneakers::Queue.new("downloads",
|
50
55
|
queue_vars.merge(:routing_key => ["alpha", "beta"]))
|
51
56
|
|
@@ -53,10 +58,33 @@ describe Sneakers::Queue do
|
|
53
58
|
mock(@mkqueue).bind(@mkex, :routing_key => "beta")
|
54
59
|
mock(@mkqueue).subscribe(:block => false, :ack => true)
|
55
60
|
|
56
|
-
q.subscribe(
|
61
|
+
q.subscribe(@mkworker)
|
57
62
|
end
|
58
|
-
end
|
59
63
|
|
64
|
+
it "will use whatever handler the worker specifies" do
|
65
|
+
mock(@mkchan).queue("downloads", :durable => true) { @mkqueue }
|
66
|
+
@handler = Object.new
|
67
|
+
worker_opts = { :handler => @handler }
|
68
|
+
stub(@mkworker).opts { worker_opts }
|
69
|
+
mock(@handler).new(@mkchan, @mkqueue, worker_opts).once
|
70
|
+
|
71
|
+
stub(@mkqueue).bind
|
72
|
+
stub(@mkqueue).subscribe
|
73
|
+
q = Sneakers::Queue.new("downloads", queue_vars)
|
74
|
+
q.subscribe(@mkworker)
|
75
|
+
end
|
60
76
|
|
77
|
+
it "creates a non-durable queue if :queue_durable => false" do
|
78
|
+
mock(@mkchan).queue("test_nondurable", :durable => false) { @mkqueue_nondurable }
|
79
|
+
queue_vars[:queue_durable] = false
|
80
|
+
q = Sneakers::Queue.new("test_nondurable", queue_vars)
|
81
|
+
|
82
|
+
mock(@mkqueue_nondurable).bind(@mkex, :routing_key => "test_nondurable")
|
83
|
+
mock(@mkqueue_nondurable).subscribe(:block => false, :ack => true)
|
84
|
+
|
85
|
+
q.subscribe(@mkworker)
|
86
|
+
myqueue = q.instance_variable_get(:@queue)
|
87
|
+
end
|
88
|
+
end
|
61
89
|
end
|
62
90
|
|
@@ -17,20 +17,21 @@ describe Sneakers do
|
|
17
17
|
|
18
18
|
describe 'self' do
|
19
19
|
it 'should have defaults set up' do
|
20
|
-
Sneakers::
|
20
|
+
Sneakers::CONFIG[:log].must_equal(STDOUT)
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'should configure itself' do
|
24
24
|
Sneakers.configure
|
25
25
|
Sneakers.logger.wont_be_nil
|
26
|
+
Sneakers.configured?.must_equal(true)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
30
|
describe '.daemonize!' do
|
30
31
|
it 'should set a logger to a default info level and not daemonize' do
|
31
32
|
Sneakers.daemonize!
|
32
|
-
Sneakers::
|
33
|
-
Sneakers::
|
33
|
+
Sneakers::CONFIG[:log].must_equal('sneakers.log')
|
34
|
+
Sneakers::CONFIG[:daemonize].must_equal(true)
|
34
35
|
Sneakers.logger.level.must_equal(Logger::INFO)
|
35
36
|
end
|
36
37
|
|
@@ -43,11 +44,11 @@ describe Sneakers do
|
|
43
44
|
|
44
45
|
describe '.clear!' do
|
45
46
|
it 'must reset dirty configuration to default' do
|
46
|
-
Sneakers::
|
47
|
+
Sneakers::CONFIG[:log].must_equal(STDOUT)
|
47
48
|
Sneakers.configure(:log => 'foobar.log')
|
48
|
-
Sneakers::
|
49
|
+
Sneakers::CONFIG[:log].must_equal('foobar.log')
|
49
50
|
Sneakers.clear!
|
50
|
-
Sneakers::
|
51
|
+
Sneakers::CONFIG[:log].must_equal(STDOUT)
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|