backburner 1.8.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 +24 -4
- data/README.md +70 -14
- data/lib/active_job/queue_adapters/backburner_adapter.rb +9 -2
- data/lib/backburner/cli.rb +1 -1
- data/lib/backburner/enqueue_pool.rb +2 -0
- data/lib/backburner/performable.rb +28 -3
- data/lib/backburner/version.rb +1 -1
- data/lib/backburner/worker.rb +38 -4
- data/lib/backburner/workers/threading.rb +16 -0
- data/lib/backburner/workers/threads_on_fork.rb +1 -0
- metadata +8 -82
- data/.github/workflows/ci.yml +0 -45
- data/.github/workflows/github-release.yml +0 -58
- data/.github/workflows/release.yml +0 -221
- data/.gitignore +0 -17
- data/CONTRIBUTING.md +0 -37
- data/Gemfile +0 -7
- data/Rakefile +0 -17
- data/TODO +0 -4
- data/backburner.gemspec +0 -31
- 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/active_job_adapter_test.rb +0 -24
- data/test/async_proxy_test.rb +0 -36
- data/test/back_burner_test.rb +0 -101
- data/test/connection_test.rb +0 -201
- data/test/fixtures/active_job_app.rb +0 -53
- data/test/fixtures/active_jobs.rb +0 -11
- data/test/fixtures/autoload/test_broken_name_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_no_method_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_require_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_runtime_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_syntax_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_timeout_job.rb +0 -4
- data/test/fixtures/autoload/test_same_name_job.rb +0 -5
- data/test/fixtures/hooked.rb +0 -122
- data/test/fixtures/test_fork_jobs.rb +0 -77
- data/test/fixtures/test_forking_jobs.rb +0 -56
- data/test/fixtures/test_jobs.rb +0 -140
- data/test/fixtures/test_queue_settings.rb +0 -54
- data/test/helpers/templogger.rb +0 -22
- data/test/helpers_test.rb +0 -462
- data/test/hooks_test.rb +0 -112
- data/test/job_test.rb +0 -207
- data/test/logger_test.rb +0 -71
- data/test/performable_test.rb +0 -138
- data/test/queue_test.rb +0 -132
- data/test/test_helper.rb +0 -182
- data/test/worker_test.rb +0 -502
- data/test/workers/forking_worker_test.rb +0 -199
- data/test/workers/simple_worker_test.rb +0 -622
- data/test/workers/threading_worker_test.rb +0 -125
- data/test/workers/threads_on_fork_worker_test.rb +0 -751
|
@@ -1,199 +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
|
-
gc_was_disabled = GC.disable # the child's body runs in this process, and disables the GC as it ends
|
|
74
|
-
GC.enable unless gc_was_disabled
|
|
75
|
-
silenced(2) do
|
|
76
|
-
worker = @worker_class.new('bar.foo')
|
|
77
|
-
worker.prepare
|
|
78
|
-
worker.fork_one_job
|
|
79
|
-
end
|
|
80
|
-
ensure
|
|
81
|
-
GC.enable unless gc_was_disabled
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# A child leaves work_one_job by an exception when a job calls exit, on a TERM or INT, or on an
|
|
85
|
-
# error work_one_job doesn't rescue, and then exits through the interpreter's teardown
|
|
86
|
-
[:raise, :shutdown].each do |how|
|
|
87
|
-
it "should disable the GC in the child before the interpreter's teardown (#{how})" do
|
|
88
|
-
Backburner::Worker.stubs(:gc_disabled_on_exit?).returns(true) # as on Ruby 3.3
|
|
89
|
-
worker = @worker_class.new('bar.foo')
|
|
90
|
-
gc_disabled = gc_disabled_at_child_exit?(worker, how) do |body|
|
|
91
|
-
worker.define_singleton_method(:work_one_job) { |*| body.call }
|
|
92
|
-
worker.fork_one_job
|
|
93
|
-
end
|
|
94
|
-
assert gc_disabled, "the child's GC was still enabled when it exited"
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
end # fork_one_job
|
|
99
|
-
|
|
100
|
-
describe "practical tests" do
|
|
101
|
-
|
|
102
|
-
before do
|
|
103
|
-
@templogger = Templogger.new('/tmp')
|
|
104
|
-
Backburner.configure { |config| config.logger = @templogger.logger }
|
|
105
|
-
$worker_test_count = 0
|
|
106
|
-
$worker_success = false
|
|
107
|
-
$worker_raise = false
|
|
108
|
-
clear_jobs!('response')
|
|
109
|
-
clear_jobs!('bar.foo.1', 'bar.foo.2', 'bar.foo.3', 'bar.foo.4', 'bar.foo.5')
|
|
110
|
-
silenced do
|
|
111
|
-
@response_worker = @worker_class.new('response')
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
after do
|
|
116
|
-
@templogger.close
|
|
117
|
-
Backburner.configure { |config| config.max_job_retries = 0; config.retry_delay = 5; config.logger = nil }
|
|
118
|
-
clear_jobs!('response')
|
|
119
|
-
clear_jobs!('bar.foo.1', 'bar.foo.2', 'bar.foo.3', 'bar.foo.4', 'bar.foo.5')
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
it "should work an enqueued job" do
|
|
124
|
-
@worker = @worker_class.new('bar.foo.1')
|
|
125
|
-
@worker_class.enqueue TestJobForking, [1, 2], :queue => "bar.foo.1"
|
|
126
|
-
@worker.prepare
|
|
127
|
-
silenced(2) do
|
|
128
|
-
@worker.fork_one_job
|
|
129
|
-
@templogger.wait_for_match(/Completed TestJobFork/m)
|
|
130
|
-
@response_worker.prepare
|
|
131
|
-
@response_worker.work_one_job
|
|
132
|
-
end
|
|
133
|
-
assert_equal 3, $worker_test_count
|
|
134
|
-
end # enqueue
|
|
135
|
-
|
|
136
|
-
it "should work for an async job" do
|
|
137
|
-
@worker = @worker_class.new('bar.foo.2')
|
|
138
|
-
TestAsyncJobForking.async(:queue => 'bar.foo.2').foo(3, 5)
|
|
139
|
-
@worker.prepare
|
|
140
|
-
silenced(4) do
|
|
141
|
-
@worker.fork_one_job
|
|
142
|
-
@templogger.wait_for_match(/Completed TestAsyncJobFork/m)
|
|
143
|
-
@response_worker.prepare
|
|
144
|
-
@response_worker.work_one_job
|
|
145
|
-
end
|
|
146
|
-
assert_equal 15, $worker_test_count
|
|
147
|
-
end # async
|
|
148
|
-
|
|
149
|
-
it "should fail quietly if there's an argument error" do
|
|
150
|
-
Backburner.configure { |config| config.max_job_retries = 0 }
|
|
151
|
-
@worker = @worker_class.new('bar.foo.3')
|
|
152
|
-
@worker_class.enqueue TestJobForking, ["bam", "foo", "bar"], :queue => "bar.foo.3"
|
|
153
|
-
@worker.prepare
|
|
154
|
-
silenced(5) do
|
|
155
|
-
@worker.fork_one_job
|
|
156
|
-
@templogger.wait_for_match(/Finished TestJobFork.*attempt 1 of 1/m)
|
|
157
|
-
end
|
|
158
|
-
assert_match(/Exception ArgumentError/, @templogger.body)
|
|
159
|
-
assert_equal 0, $worker_test_count
|
|
160
|
-
end # fail, argument
|
|
161
|
-
|
|
162
|
-
it "should support retrying jobs and burying" do
|
|
163
|
-
Backburner.configure { |config| config.max_job_retries = 1; config.retry_delay = 0 }
|
|
164
|
-
@worker = @worker_class.new('bar.foo.4')
|
|
165
|
-
@worker_class.enqueue TestRetryJobForking, ["bam", "foo"], :queue => 'bar.foo.4'
|
|
166
|
-
@worker.prepare
|
|
167
|
-
silenced(4) do
|
|
168
|
-
2.times do
|
|
169
|
-
$worker_test_count += 1
|
|
170
|
-
@worker.fork_one_job
|
|
171
|
-
end
|
|
172
|
-
@templogger.wait_for_match(/Finished TestRetryJobFork.*attempt 2 of 2/m)
|
|
173
|
-
@response_worker.prepare
|
|
174
|
-
2.times { @response_worker.work_one_job }
|
|
175
|
-
end
|
|
176
|
-
assert_equal 4, $worker_test_count
|
|
177
|
-
assert_equal false, $worker_success
|
|
178
|
-
end # retry, bury
|
|
179
|
-
|
|
180
|
-
it "should support retrying jobs and succeeds" do
|
|
181
|
-
Backburner.configure { |config| config.max_job_retries = 2; config.retry_delay = 0 }
|
|
182
|
-
@worker = @worker_class.new('bar.foo.5')
|
|
183
|
-
@worker_class.enqueue TestRetryJobForking, ["bam", "foo"], :queue => 'bar.foo.5'
|
|
184
|
-
@worker.prepare
|
|
185
|
-
silenced(4) do
|
|
186
|
-
3.times do
|
|
187
|
-
$worker_test_count += 1
|
|
188
|
-
@worker.fork_one_job
|
|
189
|
-
end
|
|
190
|
-
@templogger.wait_for_match(/Completed TestRetryJobFork/m)
|
|
191
|
-
@response_worker.prepare
|
|
192
|
-
3.times { @response_worker.work_one_job }
|
|
193
|
-
end
|
|
194
|
-
assert_equal 6, $worker_test_count
|
|
195
|
-
assert_equal true, $worker_success
|
|
196
|
-
end # retrying, succeeds
|
|
197
|
-
|
|
198
|
-
end # practical tests
|
|
199
|
-
end
|