backburner-allq 1.0.38 → 1.0.40

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
  SHA256:
3
- metadata.gz: 1d44569a854f2a26375e77a62b485851cc1970bd7bacce5948178c65e17a1f27
4
- data.tar.gz: 29d4a2408a0d7b77c6236a2fd716a07c9ddad32e1566d5d5575c99d557fcb7bf
3
+ metadata.gz: 682416738c55b9567c39530b31bfc92a8d9115b51c640494b067c9ff23cca65d
4
+ data.tar.gz: 9239e634bea3dc41131c9a4deb56d5998b6f4745e891c43a90fad4c569008c0c
5
5
  SHA512:
6
- metadata.gz: 9ea4a8b0da3978fe8567ecf7edbb4157246ad88da2acf9352038627e665f2240d877511e6f49f3775d42a54d61617c79dbbee2ccb71413a76797f1c77b01218d
7
- data.tar.gz: 9e2be902d44f1600e86941c714c8bb09e2e902c636cba0cc34fd26a2fb901e79006e48df357877a3c3cc248966090561b37d4b10d5c6d0f207d5b7ab3be4e0e5
6
+ metadata.gz: 127ae4b11fcc7651aeed81e9070a791460b2256fb2d308b559e70e9c4ba767d6c8cce5feed450e783c22415f84757e248d4b70de3fb27612317fb14283794b60
7
+ data.tar.gz: 06e8e765a1f8a6fd55ce3c0405bd319e797c59d87f5f54cebdee9bba2804d888cd8f4765bb8e02935d5b96dde7c38a756df073610106d8df8243f5dc16694f7f
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,21 @@
1
+ default:
2
+ image: ruby:3.0
3
+
4
+ stages: # List of stages for jobs, and their order of execution
5
+ - test
6
+
7
+ unit-test:
8
+ tags:
9
+ - allq
10
+ stage: test
11
+ script:
12
+ - docker-compose down || true
13
+ - docker-compose up -d || true
14
+ - sleep 10
15
+ - ruby -v
16
+ - bundle install
17
+ - bundle exec rake test TEST=test/allq/back_burner_test.rb DEBUG=true
18
+ - bundle exec rake test TEST=test/allq/worker_test.rb DEBUG=true
19
+ after_script:
20
+ - docker-compose down || true
21
+
data/deploy.sh CHANGED
@@ -1,3 +1,3 @@
1
1
  echo "Did you update the version?"
2
2
  gem build backburner-allq.gemspec
3
- gem push backburner-allq-1.0.38.gem
3
+ gem push backburner-allq-1.0.40.gem
@@ -0,0 +1,26 @@
1
+ version: '3'
2
+ services:
3
+ allq-client:
4
+ networks:
5
+ - local-net
6
+ image: "blitline/allq_client"
7
+ environment:
8
+ - SERVER_STRING=allq-server:5555
9
+ depends_on:
10
+ - allq-server
11
+ ports:
12
+ - 8090:8090
13
+ restart: unless-stopped
14
+ healthcheck:
15
+ test: ["CMD-SHELL", "echo '{\"action\":\"peek\",\"params\":{\"tube\":\"default\", \"buried\":true}}' | socat - tcp4-connect:127.0.0.1:7768"]
16
+ interval: 1m
17
+ timeout: 10s
18
+ retries: 3
19
+ allq-server:
20
+ networks:
21
+ - local-net
22
+ image: "blitline/allq_server"
23
+ restart: unless-stopped
24
+ networks:
25
+ local-net:
26
+
@@ -82,6 +82,10 @@ module Backburner
82
82
  def stats
83
83
  { 'expireds' => expireds, 'releases' => releases }
84
84
  end
85
+
86
+ def clear(tube)
87
+ @client.clear(tube)
88
+ end
85
89
  end
86
90
 
87
91
  class AllQWrapper
@@ -97,6 +101,10 @@ module Backburner
97
101
  @recent_times = []
98
102
  end
99
103
 
104
+ def clear(tube)
105
+ @client.tube_delete(tube)
106
+ end
107
+
100
108
  def touch(job)
101
109
  @client.touch_put(job.id)
102
110
  end
@@ -21,7 +21,7 @@ module Backburner
21
21
  attr_accessor :job_parser_proc # proc to parse a job body from a string
22
22
 
23
23
  def initialize
24
- @allq_url = "allq://127.0.0.1:8091"
24
+ @allq_url = "allq://127.0.0.1:8090"
25
25
  @tube_namespace = "backburner"
26
26
  @namespace_separator = "."
27
27
  @default_priority = 5
@@ -23,6 +23,10 @@ module Backburner
23
23
  connect!
24
24
  end
25
25
 
26
+ def clear(tube)
27
+ @allq_wrapper.clear(tube)
28
+ end
29
+
26
30
  # Close the connection, if it exists
27
31
  def close
28
32
  @allq_wrapper.close if @allq_wrapper
@@ -110,6 +114,11 @@ module Backburner
110
114
  }
111
115
 
112
116
  options[:shard_key] = opt[:shard_key] if opt[:shard_key]
117
+ options[:parent_id] = opt[:parent_id] if opt[:parent_id]
118
+ options[:timeout] = opt[:timeout] if opt[:timeout]
119
+ options[:run_on_timeout] = opt[:run_on_timeout] if opt[:run_on_timeout]
120
+ options[:limit] = opt[:limit] if opt[:limit]
121
+ options[:is_parent] = opt[:is_parent] if opt[:is_parent]
113
122
 
114
123
  # Overwrite originals
115
124
  opt.merge!(options)
@@ -26,11 +26,6 @@ module Backburner
26
26
  @name = body["class"] || body[:class]
27
27
  @args = body["args"] || body[:args]
28
28
  @ttr = body["ttr"] || body[:ttr]
29
- if @task.special
30
- @args ||= {}
31
- @args["special"] = @task.special.to_s
32
- end
33
-
34
29
  rescue => ex # Job was not valid format
35
30
  # self.bury
36
31
  # raise JobFormatInvalid, "Job body could not be parsed: #{ex.inspect}"
@@ -54,9 +49,28 @@ module Backburner
54
49
  return false unless res
55
50
  # Execute the job
56
51
  @hooks.around_hook_events(job_name, :around_perform, *args) do
57
- timeout_job_after(@ttr > 1 ? @ttr - 1 : @ttr) { job_class.perform(*args) }
52
+
53
+ timeout_job_after(@ttr > 1 ? @ttr - 1 : @ttr) do
54
+ # Decide if we want access to the root task
55
+ if job_class.methods.include?(:perform_with_task)
56
+ job_class.perform_with_task(@task, *args)
57
+ else
58
+ job_class.perform(*args)
59
+ end
60
+ end
61
+ end
62
+
63
+ retry_count = 0
64
+ begin
65
+ task.delete
66
+ rescue StandardError => allqex
67
+ retry_count += 1
68
+
69
+ puts "Failed to delete task, waiting #{retry_count * 10}secs"
70
+ sleep(retry_count * 10)
71
+ retry if retry_count < 3
58
72
  end
59
- task.delete
73
+
60
74
  # Invoke after perform hook
61
75
  @hooks.invoke_hook_events(job_name, :after_perform, *args)
62
76
  rescue => e
@@ -1,3 +1,3 @@
1
1
  module Backburner
2
- VERSION = "1.0.38"
2
+ VERSION = "1.0.40"
3
3
  end
@@ -168,25 +168,6 @@ module Backburner
168
168
  return
169
169
  end
170
170
 
171
- # NB: There's a slight chance here that the connection to allq has
172
- # gone down between the time we reserved / processed the job and here.
173
- num_retries = job.releases
174
- max_job_retries = resolve_max_job_retries(job.job_class)
175
- retry_status = "failed: attempt #{num_retries + 1} of #{max_job_retries + 1}"
176
- retry_delay = resolve_retry_delay(job.job_class)
177
- delay = begin
178
- resolve_retry_delay_proc(job.job_class).call(retry_delay, num_retries)
179
- rescue StandardError
180
- retry_delay
181
- end
182
-
183
- if num_retries + 1 > max_job_retries
184
- job.bury
185
- else
186
- job.release(delay)
187
- end
188
- log_job_end(job.name, "#{retry_status}, retrying in #{delay}s") if job_started_at
189
-
190
171
  handle_error(e, job.name, job.args, job)
191
172
  end
192
173
  else
@@ -0,0 +1,74 @@
1
+ require File.expand_path('test_helper', __dir__)
2
+
3
+ $backburner_sum = 0
4
+ $backburner_numbers = []
5
+
6
+ class TestBackburnerJob
7
+ include Backburner::Queue
8
+ queue 'test.jobber'
9
+
10
+ def self.perform(value, number)
11
+ $backburner_sum += value
12
+ $backburner_numbers << number
13
+ end
14
+ end
15
+
16
+ class TestWorker < Backburner::Worker; end
17
+
18
+ describe 'Backburner module' do
19
+ before do
20
+ Backburner.default_queues.clear
21
+ clear_jobs!(Backburner.configuration.primary_queue, 'test-plain', 'parent-plain', 'bar.baz.foo')
22
+ end
23
+
24
+ describe 'for work method' do
25
+ it 'invokes worker simple start' do
26
+ Backburner::Workers::Simple.expects(:start).with(%w[foo bar])
27
+ Backburner.work('foo', 'bar')
28
+ end
29
+
30
+ it 'invokes other worker if specified in configuration' do
31
+ Backburner.configure { |config| config.default_worker = TestWorker }
32
+ TestWorker.expects(:start).with(%w[foo bar])
33
+ Backburner.work('foo', 'bar')
34
+ end
35
+
36
+ it 'invokes other worker if specified in work method as options' do
37
+ TestWorker.expects(:start).with(%w[foo bar])
38
+ Backburner.work('foo', 'bar', worker: TestWorker)
39
+ end
40
+
41
+ it 'invokes worker start with no args' do
42
+ Backburner::Workers::Simple.expects(:start).with([])
43
+ Backburner.work
44
+ end
45
+ end # work!
46
+
47
+ describe 'for configuration' do
48
+ it 'remembers the tube_namespace' do
49
+ assert_equal 'demo.test', Backburner.configuration.tube_namespace
50
+ end
51
+
52
+ it 'remembers the namespace_separator' do
53
+ assert_equal '.', Backburner.configuration.namespace_separator
54
+ end
55
+
56
+ it 'disallows a reserved separator' do
57
+ assert_raises RuntimeError do
58
+ Backburner.configuration.namespace_separator = ':'
59
+ end
60
+ end
61
+ end # configuration
62
+
63
+ describe 'for default_queues' do
64
+ it 'supports assignment' do
65
+ Backburner.default_queues << 'foo'
66
+ Backburner.default_queues << 'bar'
67
+ assert_same_elements %w[foo bar], Backburner.default_queues
68
+ end
69
+ end
70
+
71
+ after do
72
+ Backburner.configure { |config| config.default_worker = Backburner::Workers::Simple }
73
+ end
74
+ end # Backburner
@@ -0,0 +1,108 @@
1
+ $LOAD_PATH.unshift File.expand_path("lib")
2
+ require 'backburner'
3
+ require 'tempfile'
4
+ require 'minitest/autorun'
5
+ require_relative '../fixtures/test_jobs'
6
+
7
+ begin
8
+ require 'mocha/setup'
9
+ rescue LoadError
10
+ require 'mocha'
11
+ end
12
+
13
+ # Configure Backburner
14
+ Backburner.configure do |config|
15
+ config.allq_url = "allq://127.0.0.1:8090"
16
+ config.tube_namespace = "demo.test"
17
+ config.on_error = lambda { |e| puts e }
18
+ end
19
+
20
+ def clear_jobs!(*tube_names)
21
+ connection = allq_connection
22
+ tube_names.each do |tube_name|
23
+ expanded_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
24
+ connection.clear(expanded_name)
25
+ end
26
+ ensure
27
+ connection.close if connection
28
+ end
29
+
30
+ def allq_connection
31
+ Backburner::Connection.new(Backburner.configuration.allq_url)
32
+ end
33
+
34
+ module Kernel
35
+ # Redirect standard out, standard error and the buffered logger for sprinkle to StringIO
36
+ # capture_stdout { any_commands; you_want } => "all output from the commands"
37
+ def capture_stdout
38
+ if ENV['DEBUG'] # Skip if debug mode
39
+ yield
40
+ return ""
41
+ end
42
+
43
+ out = StringIO.new
44
+ $stdout = out
45
+ $stderr = out
46
+ yield
47
+ return out.string
48
+ ensure
49
+ $stdout = STDOUT
50
+ $stderr = STDERR
51
+ end
52
+ end
53
+
54
+ def sleeper(duration_in_seconds)
55
+ 1.upto(duration_in_seconds) do |i|
56
+ sleep(1)
57
+ print '.'
58
+ end
59
+ end
60
+
61
+ # pop_one_job(tube_name)
62
+ def pop_one_job(tube_name=Backburner.configuration.primary_queue)
63
+ tube_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
64
+ connection = allq_connection
65
+ silenced(3) { @res = connection.get(tube_name)}
66
+ data = nil
67
+ data = Backburner.configuration.job_parser_proc.call(@res.body) if @res && @res.body
68
+ yield @res, data
69
+ ensure
70
+ connection.close if connection
71
+ end
72
+
73
+ # def work_one_job(tube_name=Backburner.configuration.primary_queue)
74
+ # tube_name = [Backburner.configuration.tube_namespace, tube_name].join(".")
75
+ # connection = allq_connection
76
+ # job = Backburner::Worker.work_one_job(connection, tube_name)
77
+ # job.delete
78
+ # end
79
+
80
+ def assert_same_elements(a1, a2, msg = nil)
81
+ [:select, :inject, :size].each do |m|
82
+ [a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
83
+ end
84
+
85
+ assert a1h = a1.inject({}) { |h,e| h[e] ||= a1.select { |i| i == e }.size; h }
86
+ assert a2h = a2.inject({}) { |h,e| h[e] ||= a2.select { |i| i == e }.size; h }
87
+
88
+ assert_equal(a1h, a2h, msg)
89
+ end
90
+
91
+ # assert_contains(['a', '1'], /\d/) => passes
92
+ # assert_contains(['a', '1'], 'a') => passes
93
+ # assert_contains(['a', '1'], /not there/) => fails
94
+ def assert_contains(collection, x, extra_msg = "")
95
+ collection = [collection] unless collection.is_a?(Array)
96
+ msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
97
+ case x
98
+ when Regexp
99
+ assert(collection.detect { |e| e =~ x }, msg)
100
+ else
101
+ assert(collection.include?(x), msg)
102
+ end
103
+ end
104
+
105
+ # silenced(5) { ... }
106
+ def silenced(time=3, &block)
107
+ Timeout::timeout(time) { capture_stdout(&block) }
108
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path('test_helper', __dir__)
2
+
3
+ describe 'Backburner::Worker module' do
4
+ before do
5
+ Backburner.default_queues.clear
6
+ clear_jobs!(Backburner.configuration.primary_queue, 'test-plain', 'parent-plain', 'bar.baz.foo')
7
+ end
8
+
9
+ it 'should support enqueuing plain job' do
10
+ Backburner::Worker.enqueue TestPlainJob, [7, 9], { ttr: 144 }
11
+ pop_one_job('test-plain') do |_job, body|
12
+ assert_equal 'TestPlainJob', body['class']
13
+ assert_equal [7, 9], body['args']
14
+ assert_equal 144, body['ttr'].to_i
15
+ end
16
+ end # plain
17
+
18
+ it 'should support enqueuing parent job' do
19
+ options = {
20
+ is_parent: true,
21
+ limit: 1,
22
+ timeout: 3,
23
+ run_on_timeout: true
24
+ }
25
+ # Enqueue parent job
26
+ response = Backburner::Worker.enqueue TestParentJob, [17, 9], options
27
+
28
+ options = {
29
+ parent_id: response.job_id
30
+ }
31
+ # Enqueue child job
32
+ Backburner::Worker.enqueue TestPlainJob, [7, 9], options
33
+ pop_one_job('test-plain') do |job, body|
34
+ assert_equal 'TestPlainJob', body['class']
35
+ assert_equal [7, 9], body['args']
36
+ job.delete
37
+ end
38
+
39
+ pop_one_job('parent-plain') do |_job, body|
40
+ assert_equal [17, 9], body['args']
41
+ end
42
+ end
43
+
44
+ it 'should support enqueuing parent job with timeout' do
45
+ options = {
46
+ is_parent: true,
47
+ limit: 1,
48
+ timeout: 3,
49
+ run_on_timeout: true
50
+ }
51
+ # Enqueue parent job
52
+ response = Backburner::Worker.enqueue TestParentJob, [17, 9], options
53
+
54
+ options = {
55
+ parent_id: response.job_id
56
+ }
57
+ # Enqueue child job
58
+ Backburner::Worker.enqueue TestPlainJob, [7, 9], options
59
+
60
+ pop_one_job('parent-plain') do |_job, body|
61
+ assert_equal body, nil
62
+ sleeper(10)
63
+ end
64
+
65
+ worker = Backburner::Workers::Simple.new('demo.test.parent-plain')
66
+ worker.prepare
67
+
68
+ TestParentJob.expects(:perform_with_task)
69
+ job = worker.work_one_job(allq_connection, 'demo.test.parent-plain')
70
+ assert_equal job.special, "true"
71
+ end
72
+
73
+
74
+
75
+ end
76
+
77
+
78
+ # options[:parent_id] = opt[:parent_id] if opt[:parent_id]
79
+ # options[:timeout] = opt[:timeout] if opt[:timeout]
80
+ # options[:run_on_timeout] = opt[:run_on_timeout] if opt[:run_on_timeout]
81
+ # options[:limit] = opt[:limit] if opt[:limit]
82
+ # options[:is_parent] = opt[:is_parent] if opt[:is_parent]
@@ -6,6 +6,18 @@ class TestPlainJob
6
6
  def self.perform(x, y); $worker_test_count += x + y + 1; end
7
7
  end
8
8
 
9
+
10
+ class TestParentJob
11
+ def self.queue; "parent-plain"; end
12
+ def self.perform(args)
13
+ puts "plain perform #{args}"
14
+ end
15
+ def self.perform_with_task(task, *args)
16
+ puts "perform_with_task"
17
+ puts task.inspect
18
+ end
19
+ end
20
+
9
21
  class TestJob
10
22
  include Backburner::Queue
11
23
  queue_priority :medium
data/test/worker_test.rb CHANGED
@@ -1,6 +1,4 @@
1
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
2
 
5
3
  describe "Backburner::Worker module" do
6
4
  before do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: backburner-allq
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.38
4
+ version: 1.0.40
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Malcolm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-27 00:00:00.000000000 Z
11
+ date: 2022-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: allq_rest
@@ -109,6 +109,7 @@ extensions: []
109
109
  extra_rdoc_files: []
110
110
  files:
111
111
  - ".gitignore"
112
+ - ".gitlab-ci.yml"
112
113
  - ".travis.yml"
113
114
  - CHANGELOG.md
114
115
  - CONTRIBUTING.md
@@ -122,6 +123,7 @@ files:
122
123
  - bin/backburner
123
124
  - circle.yml
124
125
  - deploy.sh
126
+ - docker-compose.yml
125
127
  - examples/custom.rb
126
128
  - examples/demo.rb
127
129
  - examples/god.rb
@@ -148,6 +150,9 @@ files:
148
150
  - lib/backburner/workers/simple.rb
149
151
  - lib/backburner/workers/threading.rb
150
152
  - lib/backburner/workers/threads_on_fork.rb
153
+ - test/allq/back_burner_test.rb
154
+ - test/allq/test_helper.rb
155
+ - test/allq/worker_test.rb
151
156
  - test/async_proxy_test.rb
152
157
  - test/back_burner_test.rb
153
158
  - test/connection_test.rb
@@ -193,6 +198,9 @@ signing_key:
193
198
  specification_version: 4
194
199
  summary: Reliable allq background job processing made easy for Ruby and Sinatra
195
200
  test_files:
201
+ - test/allq/back_burner_test.rb
202
+ - test/allq/test_helper.rb
203
+ - test/allq/worker_test.rb
196
204
  - test/async_proxy_test.rb
197
205
  - test/back_burner_test.rb
198
206
  - test/connection_test.rb