backburner 1.7.0 → 1.9.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 +4 -4
- data/CHANGELOG.md +53 -4
- data/HOOKS.md +23 -14
- data/README.md +102 -23
- data/bin/backburner +1 -1
- data/lib/active_job/queue_adapters/backburner_adapter.rb +19 -5
- data/lib/backburner/cli.rb +1 -1
- data/lib/backburner/configuration.rb +7 -0
- data/lib/backburner/connection.rb +4 -2
- data/lib/backburner/enqueue_pool.rb +90 -0
- data/lib/backburner/helpers.rb +77 -22
- data/lib/backburner/job.rb +46 -7
- data/lib/backburner/logger.rb +9 -0
- data/lib/backburner/performable.rb +29 -4
- data/lib/backburner/queue.rb +37 -19
- data/lib/backburner/version.rb +1 -1
- data/lib/backburner/worker.rb +150 -25
- data/lib/backburner/workers/forking.rb +4 -2
- data/lib/backburner/workers/simple.rb +5 -0
- data/lib/backburner/workers/threading.rb +17 -7
- data/lib/backburner/workers/threads_on_fork.rb +59 -23
- data/lib/backburner.rb +7 -1
- metadata +40 -66
- data/.gitignore +0 -17
- data/.travis.yml +0 -29
- data/CONTRIBUTING.md +0 -37
- data/Gemfile +0 -4
- data/Rakefile +0 -17
- data/TODO +0 -4
- data/backburner.gemspec +0 -28
- data/circle.yml +0 -3
- data/examples/custom.rb +0 -25
- data/examples/demo.rb +0 -60
- data/examples/god.rb +0 -46
- data/examples/hooked.rb +0 -87
- data/examples/retried.rb +0 -31
- data/examples/simple.rb +0 -43
- data/examples/stress.rb +0 -31
- data/test/async_proxy_test.rb +0 -36
- data/test/back_burner_test.rb +0 -88
- data/test/connection_test.rb +0 -179
- data/test/fixtures/active_jobs.rb +0 -11
- data/test/fixtures/hooked.rb +0 -122
- data/test/fixtures/test_fork_jobs.rb +0 -72
- data/test/fixtures/test_forking_jobs.rb +0 -56
- data/test/fixtures/test_jobs.rb +0 -87
- data/test/fixtures/test_queue_settings.rb +0 -14
- data/test/helpers/templogger.rb +0 -22
- data/test/helpers_test.rb +0 -278
- data/test/hooks_test.rb +0 -112
- data/test/job_test.rb +0 -185
- data/test/logger_test.rb +0 -44
- data/test/performable_test.rb +0 -88
- data/test/queue_test.rb +0 -69
- data/test/test_helper.rb +0 -125
- data/test/worker_test.rb +0 -157
- data/test/workers/forking_worker_test.rb +0 -181
- data/test/workers/simple_worker_test.rb +0 -350
- data/test/workers/threading_worker_test.rb +0 -104
- data/test/workers/threads_on_fork_worker_test.rb +0 -484
data/test/performable_test.rb
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
|
2
|
-
|
|
3
|
-
class TestObj
|
|
4
|
-
ID = 56
|
|
5
|
-
def id; ID; end
|
|
6
|
-
def self.find(id); TestObj.new if id == ID; end
|
|
7
|
-
def foo(state, state2); "bar #{state} #{state2}"; end
|
|
8
|
-
def self.bar(state, state2); "baz #{state} #{state2}"; end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
class PerformableTestObj < TestObj
|
|
12
|
-
include Backburner::Performable
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class AutomagicTestObj < TestObj
|
|
16
|
-
# Don't include Backburner::Performable because it should be automagically included
|
|
17
|
-
def qux(state, state2); "garply #{state} #{state2}" end
|
|
18
|
-
def self.garply(state, state2); "thud #{state} #{state2}" end
|
|
19
|
-
def qux?; "garply!" end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
class AsyncInstanceMethodsTestObj < PerformableTestObj; end
|
|
23
|
-
class AsyncStaticMethodsTestObj < PerformableTestObj; end
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
describe "Backburner::Performable module" do
|
|
28
|
-
after { ENV["TEST"] = nil }
|
|
29
|
-
|
|
30
|
-
describe "for async instance method" do
|
|
31
|
-
it "should invoke worker enqueue" do
|
|
32
|
-
Backburner::Worker.expects(:enqueue).with(PerformableTestObj, [56, :foo, true, false], has_entries(:pri => 5000, :queue => "foo"))
|
|
33
|
-
PerformableTestObj.new.async(:pri => 5000, :queue => "foo").foo(true, false)
|
|
34
|
-
end
|
|
35
|
-
end # async instance
|
|
36
|
-
|
|
37
|
-
describe "for async class method" do
|
|
38
|
-
it "should invoke worker enqueue" do
|
|
39
|
-
Backburner::Worker.expects(:enqueue).with(PerformableTestObj, [nil, :bar, true, false], has_entries(:pri => 5000, :queue => "foo"))
|
|
40
|
-
PerformableTestObj.async(:pri => 5000, :queue => "foo").bar(true, false)
|
|
41
|
-
end
|
|
42
|
-
end # async class
|
|
43
|
-
|
|
44
|
-
describe "for perform class method" do
|
|
45
|
-
it "should work for instance" do
|
|
46
|
-
assert_equal "bar true false", PerformableTestObj.perform(PerformableTestObj::ID, :foo, true, false)
|
|
47
|
-
end # instance
|
|
48
|
-
|
|
49
|
-
it "should work for class level" do
|
|
50
|
-
assert_equal "baz false true", PerformableTestObj.perform(nil, :bar, false, true)
|
|
51
|
-
end # class
|
|
52
|
-
end # perform
|
|
53
|
-
|
|
54
|
-
describe "for handle_asynchronously class method" do
|
|
55
|
-
it "should automagically asynchronously proxy calls to the method" do
|
|
56
|
-
Backburner::Performable.handle_asynchronously(AutomagicTestObj, :qux, :pri => 5000, :queue => "qux")
|
|
57
|
-
|
|
58
|
-
Backburner::Worker.expects(:enqueue).with(AutomagicTestObj, [56, :qux_without_async, true, false], has_entries(:pri => 5000, :queue => "qux"))
|
|
59
|
-
AutomagicTestObj.new.qux(true, false)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "should work for class methods, too" do
|
|
63
|
-
Backburner::Performable.handle_static_asynchronously(AutomagicTestObj, :garply, :pri => 5000, :queue => "garply")
|
|
64
|
-
|
|
65
|
-
Backburner::Worker.expects(:enqueue).with(AutomagicTestObj, [nil, :garply_without_async, true, false], has_entries(:pri => 5000, :queue => "garply"))
|
|
66
|
-
AutomagicTestObj.garply(true, false)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it "should correctly handle punctuation" do
|
|
70
|
-
Backburner::Performable.handle_asynchronously(AutomagicTestObj, :qux?)
|
|
71
|
-
|
|
72
|
-
Backburner::Worker.expects(:enqueue).with(AutomagicTestObj, [56, :qux_without_async?], {})
|
|
73
|
-
AutomagicTestObj.new.qux?
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "should be available for instance methods on any class that includes the Performable module" do
|
|
77
|
-
AsyncInstanceMethodsTestObj.handle_asynchronously :foo, pri: 5000, queue: 'qux'
|
|
78
|
-
Backburner::Worker.expects(:enqueue).with(AsyncInstanceMethodsTestObj, [56, :foo_without_async, true, false], has_entries(:pri => 5000, :queue => "qux"))
|
|
79
|
-
AsyncInstanceMethodsTestObj.new.foo(true, false)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "should be available for class methods on any class that includes the Performable module" do
|
|
83
|
-
AsyncStaticMethodsTestObj.handle_static_asynchronously :bar, pri: 5000, queue: 'garply'
|
|
84
|
-
Backburner::Worker.expects(:enqueue).with(AsyncStaticMethodsTestObj, [nil, :bar_without_async, true, false], has_entries(:pri => 5000, :queue => "garply"))
|
|
85
|
-
AsyncStaticMethodsTestObj.bar(true, false)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
data/test/queue_test.rb
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
|
2
|
-
|
|
3
|
-
module NestedDemo
|
|
4
|
-
class TestJobA; include Backburner::Queue; end
|
|
5
|
-
class TestJobB; include Backburner::Queue; end
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
describe "Backburner::Queue module" do
|
|
9
|
-
describe "contains known_queue_classes" do
|
|
10
|
-
it "has all defined known queues" do
|
|
11
|
-
assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobA
|
|
12
|
-
assert_contains Backburner::Worker.known_queue_classes, NestedDemo::TestJobB
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
describe "for queue method accessor" do
|
|
17
|
-
it "should return the queue name" do
|
|
18
|
-
assert_equal Backburner.configuration.primary_queue, NestedDemo::TestJobA.queue
|
|
19
|
-
end
|
|
20
|
-
end # queue_name
|
|
21
|
-
|
|
22
|
-
describe "for queue assignment method" do
|
|
23
|
-
it "should allow queue name to be assigned" do
|
|
24
|
-
NestedDemo::TestJobB.queue("nested/job")
|
|
25
|
-
assert_equal "nested/job", NestedDemo::TestJobB.queue
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it "should allow lambdas" do
|
|
29
|
-
NestedDemo::TestJobB.queue(lambda { |klass| klass.name })
|
|
30
|
-
assert_equal "NestedDemo::TestJobB", NestedDemo::TestJobB.queue
|
|
31
|
-
end
|
|
32
|
-
end # queue
|
|
33
|
-
|
|
34
|
-
describe "for queue_priority assignment method" do
|
|
35
|
-
it "should allow queue priority to be assigned" do
|
|
36
|
-
NestedDemo::TestJobB.queue_priority(1000)
|
|
37
|
-
assert_equal 1000, NestedDemo::TestJobB.queue_priority
|
|
38
|
-
end
|
|
39
|
-
end # queue_priority
|
|
40
|
-
|
|
41
|
-
describe "for queue_respond_timeout assignment method" do
|
|
42
|
-
it "should allow queue respond_timeout to be assigned" do
|
|
43
|
-
NestedDemo::TestJobB.queue_respond_timeout(300)
|
|
44
|
-
assert_equal 300, NestedDemo::TestJobB.queue_respond_timeout
|
|
45
|
-
end
|
|
46
|
-
end # queue_respond_timeout
|
|
47
|
-
|
|
48
|
-
describe "for queue_max_job_retries assignment method" do
|
|
49
|
-
it "should allow queue max_job_retries to be assigned" do
|
|
50
|
-
NestedDemo::TestJobB.queue_max_job_retries(5)
|
|
51
|
-
assert_equal 5, NestedDemo::TestJobB.queue_max_job_retries
|
|
52
|
-
end
|
|
53
|
-
end # queue_max_job_retries
|
|
54
|
-
|
|
55
|
-
describe "for queue_retry_delay assignment method" do
|
|
56
|
-
it "should allow queue retry_delay to be assigned" do
|
|
57
|
-
NestedDemo::TestJobB.queue_retry_delay(300)
|
|
58
|
-
assert_equal 300, NestedDemo::TestJobB.queue_retry_delay
|
|
59
|
-
end
|
|
60
|
-
end # queue_retry_delay
|
|
61
|
-
|
|
62
|
-
describe "for queue_retry_delay_proc assignment method" do
|
|
63
|
-
it "should allow queue retry_delay_proc to be assigned" do
|
|
64
|
-
retry_delay_proc = lambda { |x, y| x - y }
|
|
65
|
-
NestedDemo::TestJobB.queue_retry_delay_proc(retry_delay_proc)
|
|
66
|
-
assert_equal retry_delay_proc.call(2, 1), NestedDemo::TestJobB.queue_retry_delay_proc.call(2, 1)
|
|
67
|
-
end
|
|
68
|
-
end # queue_retry_delay_proc
|
|
69
|
-
end # Backburner::Queue
|
data/test/test_helper.rb
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
require 'rubygems'
|
|
2
|
-
require 'tempfile'
|
|
3
|
-
require 'minitest/autorun'
|
|
4
|
-
require 'mocha/minitest'
|
|
5
|
-
|
|
6
|
-
$LOAD_PATH.unshift File.expand_path("lib")
|
|
7
|
-
require 'backburner'
|
|
8
|
-
require File.expand_path('../helpers/templogger', __FILE__)
|
|
9
|
-
|
|
10
|
-
# Configure Backburner
|
|
11
|
-
Backburner.configure do |config|
|
|
12
|
-
config.beanstalk_url = "beanstalk://127.0.0.1"
|
|
13
|
-
config.tube_namespace = "demo.test"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
## Kernel Extensions
|
|
17
|
-
require 'stringio'
|
|
18
|
-
|
|
19
|
-
module Kernel
|
|
20
|
-
# Redirect standard out, standard error and the buffered logger for sprinkle to StringIO
|
|
21
|
-
# capture_stdout { any_commands; you_want } => "all output from the commands"
|
|
22
|
-
def capture_stdout
|
|
23
|
-
if ENV['DEBUG'] # Skip if debug mode
|
|
24
|
-
yield
|
|
25
|
-
return ""
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
out = StringIO.new
|
|
29
|
-
$stdout = out
|
|
30
|
-
$stderr = out
|
|
31
|
-
yield
|
|
32
|
-
return out.string
|
|
33
|
-
ensure
|
|
34
|
-
$stdout = STDOUT
|
|
35
|
-
$stderr = STDERR
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
class User
|
|
40
|
-
attr_accessor :id, :name
|
|
41
|
-
|
|
42
|
-
def initialize(id, name)
|
|
43
|
-
@id, @name = id, name
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
class MiniTest::Spec
|
|
48
|
-
class << self
|
|
49
|
-
alias :should :it
|
|
50
|
-
alias :context :describe
|
|
51
|
-
end
|
|
52
|
-
alias :assert_no_match :refute_match
|
|
53
|
-
alias :assert_not_nil :refute_nil
|
|
54
|
-
alias :assert_not_equal :refute_equal
|
|
55
|
-
|
|
56
|
-
# assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
|
|
57
|
-
def assert_same_elements(a1, a2, msg = nil)
|
|
58
|
-
[:select, :inject, :size].each do |m|
|
|
59
|
-
[a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
assert a1h = a1.inject({}) { |h,e| h[e] ||= a1.select { |i| i == e }.size; h }
|
|
63
|
-
assert a2h = a2.inject({}) { |h,e| h[e] ||= a2.select { |i| i == e }.size; h }
|
|
64
|
-
|
|
65
|
-
assert_equal(a1h, a2h, msg)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# assert_contains(['a', '1'], /\d/) => passes
|
|
69
|
-
# assert_contains(['a', '1'], 'a') => passes
|
|
70
|
-
# assert_contains(['a', '1'], /not there/) => fails
|
|
71
|
-
def assert_contains(collection, x, extra_msg = "")
|
|
72
|
-
collection = [collection] unless collection.is_a?(Array)
|
|
73
|
-
msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
|
|
74
|
-
case x
|
|
75
|
-
when Regexp
|
|
76
|
-
assert(collection.detect { |e| e =~ x }, msg)
|
|
77
|
-
else
|
|
78
|
-
assert(collection.include?(x), msg)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# silenced(5) { ... }
|
|
83
|
-
def silenced(time=3, &block)
|
|
84
|
-
Timeout::timeout(time) { capture_stdout(&block) }
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def beanstalk_connection
|
|
88
|
-
Backburner::Connection.new(Backburner.configuration.beanstalk_url)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# pop_one_job(tube_name)
|
|
92
|
-
def pop_one_job(tube_name=Backburner.configuration.primary_queue)
|
|
93
|
-
tube_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
|
|
94
|
-
connection = beanstalk_connection
|
|
95
|
-
connection.tubes.watch!(tube_name)
|
|
96
|
-
silenced(3) { @res = connection.tubes.reserve }
|
|
97
|
-
yield @res, Backburner.configuration.job_parser_proc.call(@res.body)
|
|
98
|
-
ensure
|
|
99
|
-
connection.close if connection
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# clear_jobs!('foo')
|
|
103
|
-
def clear_jobs!(*tube_names)
|
|
104
|
-
connection = beanstalk_connection
|
|
105
|
-
tube_names.each do |tube_name|
|
|
106
|
-
expanded_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
|
|
107
|
-
connection.tubes.find(expanded_name).clear
|
|
108
|
-
end
|
|
109
|
-
ensure
|
|
110
|
-
connection.close if connection
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
# Simulates a broken connection for any Beaneater::Connection. Will
|
|
114
|
-
# simulate a restored connection after `reconnects_after`. This is expected
|
|
115
|
-
# to be used when ensuring a Beaneater connection is open, therefore
|
|
116
|
-
def simulate_disconnect(connection, reconnects_after = 2)
|
|
117
|
-
connection.beanstalk.connection.connection.expects(:closed? => true)
|
|
118
|
-
returns = Array.new(reconnects_after - 1, stub('TCPSocket'))
|
|
119
|
-
returns.each do |socket|
|
|
120
|
-
result = (socket != returns.last)
|
|
121
|
-
socket.stubs(:closed? => result)
|
|
122
|
-
end
|
|
123
|
-
TCPSocket.expects(:new).times(returns.size).returns(*returns)
|
|
124
|
-
end
|
|
125
|
-
end # MiniTest::Spec
|
data/test/worker_test.rb
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
require File.expand_path('../test_helper', __FILE__)
|
|
2
|
-
require File.expand_path('../fixtures/test_jobs', __FILE__)
|
|
3
|
-
require File.expand_path('../fixtures/hooked', __FILE__)
|
|
4
|
-
|
|
5
|
-
describe "Backburner::Worker module" do
|
|
6
|
-
before do
|
|
7
|
-
Backburner.default_queues.clear
|
|
8
|
-
clear_jobs!(Backburner.configuration.primary_queue, "test-plain", "test.bar", "bar.baz.foo")
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe "for enqueue class method" do
|
|
12
|
-
it "should support enqueuing plain job" do
|
|
13
|
-
Backburner::Worker.enqueue TestPlainJob, [7, 9], :ttr => 100, :pri => 2000
|
|
14
|
-
pop_one_job("test-plain") do |job, body|
|
|
15
|
-
assert_equal "TestPlainJob", body["class"]
|
|
16
|
-
assert_equal [7, 9], body["args"]
|
|
17
|
-
assert_equal 100, job.ttr
|
|
18
|
-
assert_equal 2000, job.pri
|
|
19
|
-
end
|
|
20
|
-
end # plain
|
|
21
|
-
|
|
22
|
-
it "should support enqueuing job with class queue priority" do
|
|
23
|
-
Backburner::Worker.enqueue TestJob, [3, 4], :ttr => 100
|
|
24
|
-
pop_one_job do |job, body|
|
|
25
|
-
assert_equal "TestJob", body["class"]
|
|
26
|
-
assert_equal [3, 4], body["args"]
|
|
27
|
-
assert_equal 100, job.ttr
|
|
28
|
-
assert_equal 100, job.pri
|
|
29
|
-
end
|
|
30
|
-
end # queue priority
|
|
31
|
-
|
|
32
|
-
it "should support enqueuing job with specified named priority" do
|
|
33
|
-
Backburner::Worker.enqueue TestJob, [3, 4], :ttr => 100, :pri => 'high'
|
|
34
|
-
pop_one_job do |job, body|
|
|
35
|
-
assert_equal "TestJob", body["class"]
|
|
36
|
-
assert_equal [3, 4], body["args"]
|
|
37
|
-
assert_equal 100, job.ttr
|
|
38
|
-
assert_equal 0, job.pri
|
|
39
|
-
end
|
|
40
|
-
end # queue named priority
|
|
41
|
-
|
|
42
|
-
it "should support enqueuing job with class queue respond_timeout" do
|
|
43
|
-
Backburner::Worker.enqueue TestJob, [3, 4]
|
|
44
|
-
pop_one_job do |job, body|
|
|
45
|
-
assert_equal "TestJob", body["class"]
|
|
46
|
-
assert_equal [3, 4], body["args"]
|
|
47
|
-
assert_equal 300, job.ttr
|
|
48
|
-
assert_equal 100, job.pri
|
|
49
|
-
end
|
|
50
|
-
end # queue respond_timeout
|
|
51
|
-
|
|
52
|
-
it "should support enqueuing job with custom queue" do
|
|
53
|
-
Backburner::Worker.enqueue TestJob, [6, 7], :queue => "test.bar", :pri => 5000
|
|
54
|
-
pop_one_job("test.bar") do |job, body|
|
|
55
|
-
assert_equal "TestJob", body["class"]
|
|
56
|
-
assert_equal [6, 7], body["args"]
|
|
57
|
-
assert_equal 0, job.delay
|
|
58
|
-
assert_equal 5000, job.pri
|
|
59
|
-
assert_equal 300, job.ttr
|
|
60
|
-
end
|
|
61
|
-
end # custom
|
|
62
|
-
|
|
63
|
-
it "should support async job" do
|
|
64
|
-
TestAsyncJob.async(:ttr => 100, :queue => "bar.baz.foo").foo(10, 5)
|
|
65
|
-
pop_one_job("bar.baz.foo") do |job, body|
|
|
66
|
-
assert_equal "TestAsyncJob", body["class"]
|
|
67
|
-
assert_equal [nil, "foo", 10, 5], body["args"]
|
|
68
|
-
assert_equal 100, job.ttr
|
|
69
|
-
assert_equal Backburner.configuration.default_priority, job.pri
|
|
70
|
-
end
|
|
71
|
-
end # async
|
|
72
|
-
|
|
73
|
-
it "should support enqueueing job with lambda queue" do
|
|
74
|
-
expected_queue_name = TestLambdaQueueJob.calculated_queue_name
|
|
75
|
-
Backburner::Worker.enqueue TestLambdaQueueJob, [6, 7], :queue => lambda { |klass| klass.calculated_queue_name }
|
|
76
|
-
pop_one_job(expected_queue_name) do |job, body|
|
|
77
|
-
assert_equal "TestLambdaQueueJob", body["class"]
|
|
78
|
-
assert_equal [6, 7], body["args"]
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end # enqueue
|
|
82
|
-
|
|
83
|
-
describe "for start class method" do
|
|
84
|
-
it "should initialize and start the worker instance" do
|
|
85
|
-
ech = stub
|
|
86
|
-
Backburner::Worker.expects(:new).with("foo").returns(ech)
|
|
87
|
-
ech.expects(:start)
|
|
88
|
-
Backburner::Worker.start("foo")
|
|
89
|
-
end
|
|
90
|
-
end # start
|
|
91
|
-
|
|
92
|
-
describe "for tube_names accessor" do
|
|
93
|
-
before do
|
|
94
|
-
Backburner.default_queues << "baz"
|
|
95
|
-
Backburner.default_queues << "bam"
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
it "supports retrieving tubes" do
|
|
99
|
-
worker = Backburner::Worker.new(["foo", "bar"])
|
|
100
|
-
assert_equal ["foo", "bar"], worker.tube_names
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it "supports single tube array arg" do
|
|
104
|
-
worker = Backburner::Worker.new([["foo", "bar"]])
|
|
105
|
-
assert_equal ["foo", "bar"], worker.tube_names
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "supports empty nil array arg with default values" do
|
|
109
|
-
worker = Backburner::Worker.new([nil])
|
|
110
|
-
assert_equal ['baz', 'bam'], worker.tube_names
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
it "supports single tube arg" do
|
|
114
|
-
worker = Backburner::Worker.new("foo")
|
|
115
|
-
assert_equal ["foo"], worker.tube_names
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
it "supports empty array arg with default values" do
|
|
119
|
-
worker = Backburner::Worker.new([])
|
|
120
|
-
assert_equal ['baz', 'bam'], worker.tube_names
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it "supports nil arg with default values" do
|
|
124
|
-
worker = Backburner::Worker.new(nil)
|
|
125
|
-
assert_equal ['baz', 'bam'], worker.tube_names
|
|
126
|
-
end
|
|
127
|
-
end # tube_names
|
|
128
|
-
|
|
129
|
-
describe "for custom serialization" do
|
|
130
|
-
before do
|
|
131
|
-
Backburner.configure do |config|
|
|
132
|
-
@old_parser = config.job_parser_proc
|
|
133
|
-
@old_serializer = config.job_serializer_proc
|
|
134
|
-
config.job_parser_proc = lambda { |body| Marshal.load(body) }
|
|
135
|
-
config.job_serializer_proc = lambda { |body| Marshal.dump(body) }
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
after do
|
|
140
|
-
clear_jobs!('test-plain')
|
|
141
|
-
Backburner.configure do |config|
|
|
142
|
-
config.job_parser_proc = @old_parser
|
|
143
|
-
config.job_serializer_proc = @old_serializer
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
it "should support enqueuing a job" do
|
|
148
|
-
Backburner::Worker.enqueue TestPlainJob, [7, 9], :ttr => 100, :pri => 2000
|
|
149
|
-
pop_one_job("test-plain") do |job, body|
|
|
150
|
-
assert_equal "TestPlainJob", body[:class]
|
|
151
|
-
assert_equal [7, 9], body[:args]
|
|
152
|
-
assert_equal 100, job.ttr
|
|
153
|
-
assert_equal 2000, job.pri
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
end # custom serialization
|
|
157
|
-
end # Backburner::Worker
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
require File.expand_path('../../test_helper', __FILE__)
|
|
2
|
-
require File.expand_path('../../fixtures/test_forking_jobs', __FILE__)
|
|
3
|
-
|
|
4
|
-
describe "Backburner::Workers::Forking module" do
|
|
5
|
-
|
|
6
|
-
before do
|
|
7
|
-
Backburner.default_queues.clear
|
|
8
|
-
@worker_class = Backburner::Workers::Forking
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
describe "for prepare method" do
|
|
12
|
-
it "should make tube names array always unique to avoid duplication" do
|
|
13
|
-
worker = @worker_class.new(["foo", "demo.test.foo"])
|
|
14
|
-
capture_stdout { worker.prepare }
|
|
15
|
-
assert_equal ["demo.test.foo"], worker.tube_names
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "should watch specified tubes" do
|
|
19
|
-
worker = @worker_class.new(["foo", "bar"])
|
|
20
|
-
out = capture_stdout { worker.prepare }
|
|
21
|
-
assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
|
|
22
|
-
assert_same_elements ["demo.test.foo", "demo.test.bar"], worker.connection.tubes.watched.map(&:name)
|
|
23
|
-
assert_match(/demo\.test\.foo/, out)
|
|
24
|
-
end # multiple
|
|
25
|
-
|
|
26
|
-
it "should watch single tube" do
|
|
27
|
-
worker = @worker_class.new("foo")
|
|
28
|
-
out = capture_stdout { worker.prepare }
|
|
29
|
-
assert_equal ["demo.test.foo"], worker.tube_names
|
|
30
|
-
assert_same_elements ["demo.test.foo"], worker.connection.tubes.watched.map(&:name)
|
|
31
|
-
assert_match(/demo\.test\.foo/, out)
|
|
32
|
-
end # single
|
|
33
|
-
|
|
34
|
-
it "should respect default_queues settings" do
|
|
35
|
-
Backburner.default_queues.concat(["foo", "bar"])
|
|
36
|
-
worker = @worker_class.new
|
|
37
|
-
out = capture_stdout { worker.prepare }
|
|
38
|
-
assert_equal ["demo.test.foo", "demo.test.bar"], worker.tube_names
|
|
39
|
-
assert_same_elements ["demo.test.foo", "demo.test.bar"], worker.connection.tubes.watched.map(&:name)
|
|
40
|
-
assert_match(/demo\.test\.foo/, out)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it "should assign based on all tubes" do
|
|
44
|
-
@worker_class.any_instance.expects(:all_existing_queues).once.returns("bar")
|
|
45
|
-
worker = @worker_class.new
|
|
46
|
-
out = capture_stdout { worker.prepare }
|
|
47
|
-
assert_equal ["demo.test.bar"], worker.tube_names
|
|
48
|
-
assert_same_elements ["demo.test.bar"], worker.connection.tubes.watched.map(&:name)
|
|
49
|
-
assert_match(/demo\.test\.bar/, out)
|
|
50
|
-
end # all assign
|
|
51
|
-
|
|
52
|
-
it "should properly retrieve all tubes" do
|
|
53
|
-
worker = @worker_class.new
|
|
54
|
-
out = capture_stdout { worker.prepare }
|
|
55
|
-
assert_contains worker.tube_names, "demo.test.backburner-jobs"
|
|
56
|
-
assert_contains worker.connection.tubes.watched.map(&:name), "demo.test.backburner-jobs"
|
|
57
|
-
assert_match(/demo\.test\.backburner-jobs/, out)
|
|
58
|
-
end # all read
|
|
59
|
-
end # prepare
|
|
60
|
-
|
|
61
|
-
describe "for fork_one_job method" do
|
|
62
|
-
|
|
63
|
-
it "should fork, work job, and exit" do
|
|
64
|
-
clear_jobs!("bar.foo")
|
|
65
|
-
@worker_class.enqueue TestJobForking, [1, 2], :queue => "bar.foo"
|
|
66
|
-
|
|
67
|
-
fake_pid = 45
|
|
68
|
-
Process.expects(:fork).returns(fake_pid).yields
|
|
69
|
-
@worker_class.any_instance.expects(:work_one_job)
|
|
70
|
-
@worker_class.any_instance.expects(:coolest_exit)
|
|
71
|
-
Process.expects(:wait).with(fake_pid)
|
|
72
|
-
|
|
73
|
-
silenced(2) do
|
|
74
|
-
worker = @worker_class.new('bar.foo')
|
|
75
|
-
worker.prepare
|
|
76
|
-
worker.fork_one_job
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
end # fork_one_job
|
|
81
|
-
|
|
82
|
-
describe "practical tests" do
|
|
83
|
-
|
|
84
|
-
before do
|
|
85
|
-
@templogger = Templogger.new('/tmp')
|
|
86
|
-
Backburner.configure { |config| config.logger = @templogger.logger }
|
|
87
|
-
$worker_test_count = 0
|
|
88
|
-
$worker_success = false
|
|
89
|
-
$worker_raise = false
|
|
90
|
-
clear_jobs!('response')
|
|
91
|
-
clear_jobs!('bar.foo.1', 'bar.foo.2', 'bar.foo.3', 'bar.foo.4', 'bar.foo.5')
|
|
92
|
-
silenced do
|
|
93
|
-
@response_worker = @worker_class.new('response')
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
after do
|
|
98
|
-
@templogger.close
|
|
99
|
-
Backburner.configuration.logger = nil
|
|
100
|
-
clear_jobs!('response')
|
|
101
|
-
clear_jobs!('bar.foo.1', 'bar.foo.2', 'bar.foo.3', 'bar.foo.4', 'bar.foo.5')
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
it "should work an enqueued job" do
|
|
106
|
-
@worker = @worker_class.new('bar.foo.1')
|
|
107
|
-
@worker_class.enqueue TestJobForking, [1, 2], :queue => "bar.foo.1"
|
|
108
|
-
@worker.prepare
|
|
109
|
-
silenced(2) do
|
|
110
|
-
@worker.fork_one_job
|
|
111
|
-
@templogger.wait_for_match(/Completed TestJobFork/m)
|
|
112
|
-
@response_worker.prepare
|
|
113
|
-
@response_worker.work_one_job
|
|
114
|
-
end
|
|
115
|
-
assert_equal 3, $worker_test_count
|
|
116
|
-
end # enqueue
|
|
117
|
-
|
|
118
|
-
it "should work for an async job" do
|
|
119
|
-
@worker = @worker_class.new('bar.foo.2')
|
|
120
|
-
TestAsyncJobForking.async(:queue => 'bar.foo.2').foo(3, 5)
|
|
121
|
-
@worker.prepare
|
|
122
|
-
silenced(4) do
|
|
123
|
-
@worker.fork_one_job
|
|
124
|
-
@templogger.wait_for_match(/Completed TestAsyncJobFork/m)
|
|
125
|
-
@response_worker.prepare
|
|
126
|
-
@response_worker.work_one_job
|
|
127
|
-
end
|
|
128
|
-
assert_equal 15, $worker_test_count
|
|
129
|
-
end # async
|
|
130
|
-
|
|
131
|
-
it "should fail quietly if there's an argument error" do
|
|
132
|
-
Backburner.configure { |config| config.max_job_retries = 0 }
|
|
133
|
-
@worker = @worker_class.new('bar.foo.3')
|
|
134
|
-
@worker_class.enqueue TestJobForking, ["bam", "foo", "bar"], :queue => "bar.foo.3"
|
|
135
|
-
@worker.prepare
|
|
136
|
-
silenced(5) do
|
|
137
|
-
@worker.fork_one_job
|
|
138
|
-
@templogger.wait_for_match(/Finished TestJobFork.*attempt 1 of 1/m)
|
|
139
|
-
end
|
|
140
|
-
assert_match(/Exception ArgumentError/, @templogger.body)
|
|
141
|
-
assert_equal 0, $worker_test_count
|
|
142
|
-
end # fail, argument
|
|
143
|
-
|
|
144
|
-
it "should support retrying jobs and burying" do
|
|
145
|
-
Backburner.configure { |config| config.max_job_retries = 1; config.retry_delay = 0 }
|
|
146
|
-
@worker = @worker_class.new('bar.foo.4')
|
|
147
|
-
@worker_class.enqueue TestRetryJobForking, ["bam", "foo"], :queue => 'bar.foo.4'
|
|
148
|
-
@worker.prepare
|
|
149
|
-
silenced(4) do
|
|
150
|
-
2.times do
|
|
151
|
-
$worker_test_count += 1
|
|
152
|
-
@worker.fork_one_job
|
|
153
|
-
end
|
|
154
|
-
@templogger.wait_for_match(/Finished TestRetryJobFork.*attempt 2 of 2/m)
|
|
155
|
-
@response_worker.prepare
|
|
156
|
-
2.times { @response_worker.work_one_job }
|
|
157
|
-
end
|
|
158
|
-
assert_equal 4, $worker_test_count
|
|
159
|
-
assert_equal false, $worker_success
|
|
160
|
-
end # retry, bury
|
|
161
|
-
|
|
162
|
-
it "should support retrying jobs and succeeds" do
|
|
163
|
-
Backburner.configure { |config| config.max_job_retries = 2; config.retry_delay = 0 }
|
|
164
|
-
@worker = @worker_class.new('bar.foo.5')
|
|
165
|
-
@worker_class.enqueue TestRetryJobForking, ["bam", "foo"], :queue => 'bar.foo.5'
|
|
166
|
-
@worker.prepare
|
|
167
|
-
silenced(4) do
|
|
168
|
-
3.times do
|
|
169
|
-
$worker_test_count += 1
|
|
170
|
-
@worker.fork_one_job
|
|
171
|
-
end
|
|
172
|
-
@templogger.wait_for_match(/Completed TestRetryJobFork/m)
|
|
173
|
-
@response_worker.prepare
|
|
174
|
-
3.times { @response_worker.work_one_job }
|
|
175
|
-
end
|
|
176
|
-
assert_equal 6, $worker_test_count
|
|
177
|
-
assert_equal true, $worker_success
|
|
178
|
-
end # retrying, succeeds
|
|
179
|
-
|
|
180
|
-
end # practical tests
|
|
181
|
-
end
|