backburner 1.6.1 → 1.8.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +45 -0
  3. data/.github/workflows/github-release.yml +58 -0
  4. data/.github/workflows/release.yml +221 -0
  5. data/CHANGELOG.md +33 -0
  6. data/Gemfile +4 -1
  7. data/HOOKS.md +23 -14
  8. data/README.md +32 -9
  9. data/backburner.gemspec +6 -1
  10. data/bin/backburner +1 -1
  11. data/lib/active_job/queue_adapters/backburner_adapter.rb +41 -0
  12. data/lib/backburner/configuration.rb +7 -0
  13. data/lib/backburner/connection.rb +4 -2
  14. data/lib/backburner/enqueue_pool.rb +88 -0
  15. data/lib/backburner/helpers.rb +77 -22
  16. data/lib/backburner/job.rb +46 -7
  17. data/lib/backburner/logger.rb +9 -0
  18. data/lib/backburner/performable.rb +1 -1
  19. data/lib/backburner/queue.rb +37 -19
  20. data/lib/backburner/version.rb +1 -1
  21. data/lib/backburner/worker.rb +112 -21
  22. data/lib/backburner/workers/forking.rb +4 -2
  23. data/lib/backburner/workers/simple.rb +5 -0
  24. data/lib/backburner/workers/threading.rb +1 -7
  25. data/lib/backburner/workers/threads_on_fork.rb +58 -23
  26. data/lib/backburner.rb +7 -0
  27. data/test/active_job_adapter_test.rb +24 -0
  28. data/test/back_burner_test.rb +13 -0
  29. data/test/connection_test.rb +22 -0
  30. data/test/fixtures/active_job_app.rb +53 -0
  31. data/test/fixtures/active_jobs.rb +11 -0
  32. data/test/fixtures/autoload/test_broken_name_job.rb +4 -0
  33. data/test/fixtures/autoload/test_broken_no_method_job.rb +4 -0
  34. data/test/fixtures/autoload/test_broken_require_job.rb +4 -0
  35. data/test/fixtures/autoload/test_broken_runtime_job.rb +4 -0
  36. data/test/fixtures/autoload/test_broken_syntax_job.rb +4 -0
  37. data/test/fixtures/autoload/test_broken_timeout_job.rb +4 -0
  38. data/test/fixtures/autoload/test_same_name_job.rb +5 -0
  39. data/test/fixtures/test_fork_jobs.rb +5 -0
  40. data/test/fixtures/test_jobs.rb +53 -0
  41. data/test/fixtures/test_queue_settings.rb +41 -1
  42. data/test/helpers/templogger.rb +1 -1
  43. data/test/helpers_test.rb +184 -0
  44. data/test/job_test.rb +22 -0
  45. data/test/logger_test.rb +27 -0
  46. data/test/performable_test.rb +50 -0
  47. data/test/queue_test.rb +63 -0
  48. data/test/test_helper.rb +59 -5
  49. data/test/worker_test.rb +346 -1
  50. data/test/workers/forking_worker_test.rb +19 -1
  51. data/test/workers/simple_worker_test.rb +272 -0
  52. data/test/workers/threading_worker_test.rb +22 -1
  53. data/test/workers/threads_on_fork_worker_test.rb +279 -12
  54. metadata +87 -8
  55. data/.travis.yml +0 -29
  56. data/circle.yml +0 -3
data/test/worker_test.rb CHANGED
@@ -5,7 +5,7 @@ require File.expand_path('../fixtures/hooked', __FILE__)
5
5
  describe "Backburner::Worker module" do
6
6
  before do
7
7
  Backburner.default_queues.clear
8
- clear_jobs!(Backburner.configuration.primary_queue, "test-plain", "test.bar", "bar.baz.foo")
8
+ clear_jobs!(Backburner.configuration.primary_queue, "test-plain", "test.bar", "bar.baz.foo", "test-parent")
9
9
  end
10
10
 
11
11
  describe "for enqueue class method" do
@@ -49,6 +49,28 @@ describe "Backburner::Worker module" do
49
49
  end
50
50
  end # queue respond_timeout
51
51
 
52
+ it "should enqueue a subclass job on its superclass queue with its settings" do
53
+ Backburner::Worker.enqueue TestChildQueueJob, [3, 4]
54
+ pop_one_job("test-parent") do |job, body|
55
+ assert_equal "TestChildQueueJob", body["class"]
56
+ assert_equal [3, 4], body["args"]
57
+ assert_equal 250, job.ttr
58
+ assert_equal 0, job.pri
59
+ end
60
+ end # subclass queue
61
+
62
+ it "should support a priority label as the default priority" do
63
+ default_priority = Backburner.configuration.default_priority
64
+ Backburner.configuration.default_priority = :low
65
+ Backburner::Worker.enqueue TestPlainJob, [1, 2]
66
+ pop_one_job("test-plain") do |job, body|
67
+ assert_equal "TestPlainJob", body["class"]
68
+ assert_equal 200, job.pri
69
+ end
70
+ ensure
71
+ Backburner.configuration.default_priority = default_priority
72
+ end # default priority label
73
+
52
74
  it "should support enqueuing job with custom queue" do
53
75
  Backburner::Worker.enqueue TestJob, [6, 7], :queue => "test.bar", :pri => 5000
54
76
  pop_one_job("test.bar") do |job, body|
@@ -60,6 +82,31 @@ describe "Backburner::Worker module" do
60
82
  end
61
83
  end # custom
62
84
 
85
+ it "should round a fractional delay up to whole seconds, so the job never runs early" do
86
+ conn = beanstalk_connection
87
+ { nil => 0, -1 => 0, 0 => 0, 0.2 => 1, 1 => 1, 1.5 => 2, 2 => 2 }.each do |delay, expected|
88
+ response = Backburner::Worker.enqueue TestPlainJob, [1, 2], :delay => delay
89
+ assert_equal expected, conn.jobs.find(response[:id]).stats.delay, "delay #{delay.inspect}"
90
+ end
91
+ ensure
92
+ conn.close if conn
93
+ clear_jobs!("test-plain")
94
+ end # fractional delay
95
+
96
+ it "should round a fractional TTR up to whole seconds, from an option, a class or the default" do
97
+ respond_timeout = Backburner.configuration.respond_timeout
98
+ conn = beanstalk_connection
99
+ ttr_of = lambda { |response| conn.jobs.find(response[:id]).stats.ttr }
100
+ assert_equal 1, ttr_of.call(Backburner::Worker.enqueue(TestPlainJob, [1, 2], :ttr => 0.2))
101
+ assert_equal 2, ttr_of.call(Backburner::Worker.enqueue(TestFloatRespondTimeoutJob, []))
102
+ Backburner.configuration.respond_timeout = 2.5
103
+ assert_equal 3, ttr_of.call(Backburner::Worker.enqueue(TestPlainJob, [1, 2]))
104
+ ensure
105
+ Backburner.configuration.respond_timeout = respond_timeout
106
+ conn.close if conn
107
+ clear_jobs!("test-plain")
108
+ end # fractional ttr
109
+
63
110
  it "should support async job" do
64
111
  TestAsyncJob.async(:ttr => 100, :queue => "bar.baz.foo").foo(10, 5)
65
112
  pop_one_job("bar.baz.foo") do |job, body|
@@ -80,6 +127,282 @@ describe "Backburner::Worker module" do
80
127
  end
81
128
  end # enqueue
82
129
 
130
+ describe "for the enqueue connections" do
131
+ before do
132
+ GC.start # closes the connections earlier tests left to the garbage collector before a test counts them
133
+ @gc_was_disabled = GC.disable # and keeps a collection from closing one while it counts
134
+ @stats_connection = beanstalk_connection
135
+ @beanstalk_url = Backburner.configuration.beanstalk_url
136
+ end
137
+
138
+ after do
139
+ GC.enable unless @gc_was_disabled
140
+ @stats_connection.close
141
+ Backburner.configuration.beanstalk_url = @beanstalk_url
142
+ end
143
+
144
+ # Connections beanstalkd has accepted so far
145
+ def total_connections
146
+ @stats_connection.stats.total_connections
147
+ end
148
+
149
+ def open_connections
150
+ @stats_connection.stats.current_connections
151
+ end
152
+
153
+ def enqueue(n = 0)
154
+ Backburner::Worker.enqueue(TestJob, [n, 0])
155
+ end
156
+
157
+ # Starts the pool afresh: a new URL (spelling the same beanstalkd) closes its idle connections.
158
+ # Leaves one idle connection in it.
159
+ def fresh_pool
160
+ ["beanstalk://127.0.0.1:11300", "beanstalk://127.0.0.1:11300/"].each do |url|
161
+ Backburner.configuration.beanstalk_url = url
162
+ enqueue
163
+ end
164
+ settle
165
+ end
166
+
167
+ # Waits for beanstalkd to have seen the connections closed so far
168
+ def settle
169
+ last = nil
170
+ wait_for(5) { (now = open_connections) == last || (last = now; sleep 0.1; false) }
171
+ end
172
+
173
+ it "should reuse a connection for sequential enqueues" do
174
+ enqueue
175
+ before_count = total_connections
176
+ responses = Array.new(5) { |i| enqueue(i) }
177
+ assert_equal ["INSERTED"] * 5, responses.map { |res| res[:status] }
178
+ assert_equal 0, total_connections - before_count
179
+ end
180
+
181
+ it "should reuse a connection across fibers and threads" do
182
+ enqueue
183
+ before_count = total_connections
184
+ 5.times { |i| Fiber.new { enqueue(i) }.resume }
185
+ 5.times { |i| Thread.new { enqueue(i) }.join }
186
+ assert_equal 0, total_connections - before_count
187
+ end
188
+
189
+ it "should keep at most 5 idle connections after concurrent enqueues" do
190
+ fresh_pool # one idle connection
191
+ before_total, before_open = total_connections, open_connections
192
+ threads, inside = 8, Queue.new
193
+ release = Queue.new
194
+ serializer = Backburner.configuration.job_serializer_proc
195
+ # every thread holds a connection until all of them do
196
+ Backburner.configuration.job_serializer_proc = lambda { |body| inside << 1; release.pop; body.to_json }
197
+ workers = Array.new(threads) { |i| Thread.new { enqueue(i) } }
198
+ threads.times { inside.pop }
199
+ threads.times { release << 1 }
200
+ workers.each(&:join)
201
+ Backburner.configuration.job_serializer_proc = serializer
202
+ assert_equal threads - 1, total_connections - before_total, "one reused, the rest opened"
203
+ kept = 5
204
+ wait_for(5) { open_connections - before_open == kept - 1 }
205
+ assert_equal kept - 1, open_connections - before_open, "only #{kept} stay open"
206
+ ensure
207
+ Backburner.configuration.job_serializer_proc = serializer if serializer
208
+ end
209
+
210
+ it "should give a forked child its own connection" do
211
+ skip "needs fork" unless Process.respond_to?(:fork)
212
+ enqueue(1)
213
+ before_child = total_connections
214
+ pid = Process.fork do
215
+ res = Backburner::Worker.enqueue(TestJob, [2, 0]) rescue nil
216
+ exit!(res && res[:status] == "INSERTED" ? 0 : 1)
217
+ end
218
+ Process.wait(pid)
219
+ assert_equal 0, $?.exitstatus, "the child's enqueue failed"
220
+ assert_equal 1, total_connections - before_child, "the child should open its own connection"
221
+ assert_equal "INSERTED", enqueue(3)[:status]
222
+ assert_equal 1, total_connections - before_child, "the parent should keep its connection"
223
+ end
224
+
225
+ it "should close a connection that an error interrupted instead of reusing it" do
226
+ fresh_pool # one idle connection
227
+ before_total, before_open = total_connections, open_connections
228
+ serializer = Backburner.configuration.job_serializer_proc
229
+ Backburner.configuration.job_serializer_proc = lambda { |body| raise Timeout::Error }
230
+ assert_raises(Timeout::Error) { enqueue(2) }
231
+ Backburner.configuration.job_serializer_proc = serializer
232
+ wait_for(5) { open_connections == before_open - 1 }
233
+ assert_equal before_open - 1, open_connections, "the interrupted connection should be closed"
234
+ assert_equal "INSERTED", enqueue(3)[:status]
235
+ assert_equal 1, total_connections - before_total, "the next enqueue should open a new connection"
236
+ ensure
237
+ Backburner.configuration.job_serializer_proc = serializer if serializer
238
+ end
239
+
240
+ it "should close a connection whose enqueue was killed" do
241
+ fresh_pool # one idle connection
242
+ before_total, before_open = total_connections, open_connections
243
+ serializer = Backburner.configuration.job_serializer_proc
244
+ inside = Queue.new
245
+ Backburner.configuration.job_serializer_proc = lambda { |body| inside << 1; sleep }
246
+ thread = Thread.new { enqueue(2) }
247
+ inside.pop
248
+ thread.kill.join
249
+ Backburner.configuration.job_serializer_proc = serializer
250
+ wait_for(5) { open_connections == before_open - 1 }
251
+ assert_equal before_open - 1, open_connections, "the killed enqueue's connection should be closed"
252
+ assert_equal "INSERTED", enqueue(3)[:status]
253
+ assert_equal 1, total_connections - before_total, "the next enqueue should open a new connection"
254
+ ensure
255
+ Backburner.configuration.job_serializer_proc = serializer if serializer
256
+ end
257
+
258
+ it "should replace a connection idle for longer than enqueue_connection_max_idle" do
259
+ max_idle = Backburner.configuration.enqueue_connection_max_idle
260
+ fresh_pool # one idle connection
261
+ before_total, before_open = total_connections, open_connections
262
+ Backburner.configuration.enqueue_connection_max_idle = 0.05
263
+ sleep 0.1
264
+ assert_equal "INSERTED", enqueue(1)[:status]
265
+ assert_equal 1, total_connections - before_total, "the expired connection should be replaced"
266
+ wait_for(5) { open_connections == before_open }
267
+ assert_equal before_open, open_connections, "the expired connection should be closed"
268
+ Backburner.configuration.enqueue_connection_max_idle = 60
269
+ assert_equal "INSERTED", enqueue(2)[:status]
270
+ assert_equal 1, total_connections - before_total, "a fresh connection should be reused"
271
+ ensure
272
+ Backburner.configuration.enqueue_connection_max_idle = max_idle
273
+ end
274
+
275
+ describe "when beanstalkd goes away" do
276
+ before do
277
+ pick_beanstalkd_port
278
+ @beanstalk_url = Backburner.configuration.beanstalk_url
279
+ Backburner.configuration.beanstalk_url = "beanstalk://127.0.0.1:#{@port}"
280
+ start_beanstalkd
281
+ end
282
+
283
+ after do
284
+ stop_beanstalkd
285
+ Backburner.configuration.beanstalk_url = @beanstalk_url if @beanstalk_url
286
+ end
287
+
288
+ it "should recover from a restart and from Beaneater::NotConnected" do
289
+ Thread.new do
290
+ assert_equal "INSERTED", Backburner::Worker.enqueue(TestJob, [1, 0])[:status]
291
+ stop_beanstalkd
292
+ start_beanstalkd
293
+ assert_equal "INSERTED", Backburner::Worker.enqueue(TestJob, [2, 0])[:status]
294
+ stop_beanstalkd
295
+ assert_raises(Beaneater::NotConnected) { Backburner::Worker.enqueue(TestJob, [3, 0]) }
296
+ start_beanstalkd
297
+ assert_equal "INSERTED", Backburner::Worker.enqueue(TestJob, [4, 0])[:status]
298
+ end.join
299
+ end
300
+ end # beanstalkd goes away
301
+ end # enqueue connection
302
+
303
+ describe "without a tube_namespace" do
304
+ before { @tube_namespace = Backburner.configuration.tube_namespace }
305
+ after { Backburner.configuration.tube_namespace = @tube_namespace }
306
+
307
+ def reserve_from(tube_name)
308
+ connection = beanstalk_connection
309
+ connection.tubes.watch!(tube_name)
310
+ job = connection.tubes.reserve(1)
311
+ job.delete
312
+ Backburner.configuration.job_parser_proc.call(job.body)
313
+ ensure
314
+ connection.close if connection
315
+ end
316
+
317
+ it "should enqueue on unprefixed tubes when tube_namespace is nil or false" do
318
+ [nil, false].each do |namespace|
319
+ Backburner.configuration.tube_namespace = namespace
320
+ Backburner::Worker.enqueue TestJob, [1, namespace.inspect]
321
+ Backburner::Worker.enqueue TestJob, [2, namespace.inspect], :queue => "test-no-namespace"
322
+ assert_equal [1, namespace.inspect], reserve_from("backburner-jobs")["args"]
323
+ assert_equal [2, namespace.inspect], reserve_from("test-no-namespace")["args"]
324
+ end
325
+ end
326
+
327
+ it "should enqueue on the tubes 1.7.0 used when tube_namespace is empty" do
328
+ Backburner.configuration.tube_namespace = ""
329
+ Backburner::Worker.enqueue TestJob, [1, 2]
330
+ Backburner::Worker.enqueue TestJob, [3, 4], :queue => "test-no-namespace"
331
+ assert_equal [1, 2], reserve_from(".backburner-jobs")["args"]
332
+ assert_equal [3, 4], reserve_from(".test-no-namespace")["args"]
333
+ end
334
+
335
+ it "should list existing unprefixed tubes for a worker given no tubes" do
336
+ Backburner.configuration.tube_namespace = false
337
+ Backburner::Worker.enqueue TestJob, [1, 2], :queue => "test-no-namespace"
338
+ assert_contains Backburner::Worker.new(nil).tube_names, "test-no-namespace"
339
+ reserve_from("test-no-namespace")
340
+ end
341
+ end # without a tube_namespace
342
+
343
+ describe "for a worker given no tubes" do
344
+ before do
345
+ @tube_namespace = Backburner.configuration.tube_namespace
346
+ @namespace_separator = Backburner.configuration.namespace_separator
347
+ end
348
+ after do
349
+ Backburner.configuration.tube_namespace = @tube_namespace
350
+ Backburner.configuration.namespace_separator = @namespace_separator
351
+ end
352
+
353
+ # Namespaces, separators and queue names (ActiveJob's queue_name_prefix gives "production_mailers") whose
354
+ # tubes the worker used to miss: it expanded the tube names it found on the server again ("a--b" raised)
355
+ it "should watch the tubes enqueued on for its namespace, under their names on the server" do
356
+ [["MyApp", ".", "default"], ["jobs(eu)", ".", "default"], ["app+", ".", "default"], ["bb-discovery", "_", "default"],
357
+ ["production", ".", "production_mailers"], ["bb-discovery", ".", "report_2026"], ["bb-discovery", ".", "a__b"]].each do |namespace, separator, queue|
358
+ Backburner.configuration.tube_namespace = namespace
359
+ Backburner.configuration.namespace_separator = separator
360
+ tube_name = Backburner::Worker.expand_tube_name(queue)
361
+ connection = beanstalk_connection # no jobs left in this namespace for the worker to take first
362
+ connection.tubes.all.select { |tube| tube.name.start_with?("#{namespace}#{separator}") }.each(&:clear)
363
+ connection.close
364
+ Backburner::Worker.enqueue TestJob, [1, 2], :queue => queue
365
+
366
+ [Backburner::Workers::Simple, Backburner::Workers::Forking, Backburner::Workers::Threading, Backburner::Workers::ThreadsOnFork].each do |worker_class|
367
+ worker = worker_class.new(nil)
368
+ capture_stdout { worker.prepare }
369
+ worker.connection.close
370
+ assert_contains worker.tube_names, tube_name, "#{worker_class.name} #{[namespace, separator, queue].inspect}"
371
+ end
372
+ $worker_test_count = 0
373
+ worker = Backburner::Workers::Simple.new(nil)
374
+ silenced(3) { worker.prepare; worker.work_one_job }
375
+ worker.connection.close
376
+ assert_equal 3, $worker_test_count, [namespace, separator, queue].inspect
377
+ end
378
+ end
379
+
380
+ # Another app's tubes on a shared server: the worker expanded them into tubes nobody enqueues on, so it never took
381
+ # their jobs, and mustn't start to
382
+ it "should leave out the tubes its namespace and separator can't give" do
383
+ [[["bb-discovery_admin", "_"], ["bb-discovery", "_"]], [["MyApp.Admin", "."], ["MyApp", "."]],
384
+ [["bb-other", "."], ["bb:disc", "."]]].each do |(other_namespace, other_separator), (namespace, separator)|
385
+ Backburner.configuration.tube_namespace = other_namespace
386
+ Backburner.configuration.namespace_separator = other_separator
387
+ other_tube = Backburner::Worker.expand_tube_name("reports")
388
+ begin
389
+ Backburner::Worker.enqueue TestJob, [1, 2], :queue => "reports"
390
+ Backburner.configuration.tube_namespace = namespace
391
+ Backburner.configuration.namespace_separator = separator
392
+ worker = Backburner::Workers::Simple.new(nil)
393
+ capture_stdout { worker.prepare }
394
+ worker.connection.close
395
+ refute_includes worker.tube_names, other_tube, namespace
396
+ assert_equal ["bb"], worker.tube_names, namespace if namespace == "bb:disc" # a ':' cuts every tube name to "bb"
397
+ ensure
398
+ connection = beanstalk_connection
399
+ connection.tubes.find(other_tube).clear
400
+ connection.close
401
+ end
402
+ end
403
+ end
404
+ end # given no tubes
405
+
83
406
  describe "for start class method" do
84
407
  it "should initialize and start the worker instance" do
85
408
  ech = stub
@@ -89,6 +412,28 @@ describe "Backburner::Worker module" do
89
412
  end
90
413
  end # start
91
414
 
415
+ describe "for gc_disabled_on_exit? class method" do
416
+ it "should be true only on CRuby 3.3, the Ruby whose forked children can crash as they exit" do
417
+ assert Backburner::Worker.gc_disabled_on_exit?("ruby", "3.3.6")
418
+ %w(2.7.8 3.2.6 3.4.1 4.0.0).each do |version|
419
+ refute Backburner::Worker.gc_disabled_on_exit?("ruby", version), version
420
+ end
421
+ refute Backburner::Worker.gc_disabled_on_exit?("jruby", "3.3.0")
422
+ end
423
+ end # gc_disabled_on_exit?
424
+
425
+ describe "with an anonymous subclass of a queue class" do
426
+ before { @anonymous = Class.new(TestNamedQueueJob) }
427
+ after { Backburner::Worker.known_queue_classes.delete(@anonymous) }
428
+
429
+ it "should leave it out of the known queues of a worker given no tubes" do
430
+ [Backburner::Workers::Simple, Backburner::Workers::Threading, Backburner::Workers::ThreadsOnFork].each do |worker_class|
431
+ assert_contains worker_class.new(nil).tube_names.map { |name| Backburner::Worker.expand_tube_name(name) },
432
+ Backburner::Worker.expand_tube_name("testnamedqueuejob"), worker_class.name
433
+ end
434
+ end
435
+ end # anonymous subclass
436
+
92
437
  describe "for tube_names accessor" do
93
438
  before do
94
439
  Backburner.default_queues << "baz"
@@ -70,11 +70,29 @@ describe "Backburner::Workers::Forking module" do
70
70
  @worker_class.any_instance.expects(:coolest_exit)
71
71
  Process.expects(:wait).with(fake_pid)
72
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
73
75
  silenced(2) do
74
76
  worker = @worker_class.new('bar.foo')
75
77
  worker.prepare
76
78
  worker.fork_one_job
77
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
78
96
  end
79
97
 
80
98
  end # fork_one_job
@@ -96,7 +114,7 @@ describe "Backburner::Workers::Forking module" do
96
114
 
97
115
  after do
98
116
  @templogger.close
99
- Backburner.configuration.logger = nil
117
+ Backburner.configure { |config| config.max_job_retries = 0; config.retry_delay = 5; config.logger = nil }
100
118
  clear_jobs!('response')
101
119
  clear_jobs!('bar.foo.1', 'bar.foo.2', 'bar.foo.3', 'bar.foo.4', 'bar.foo.5')
102
120
  end