disquo 0.3.0 → 0.3.1

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
  SHA1:
3
- metadata.gz: 1f9ffa4b76dc43b762c79ff560a981b71d8e6bfb
4
- data.tar.gz: 4c320fe08f60dd1d9fc18a190e65ef73d06cff64
3
+ metadata.gz: e4a5a02702349eb8b6c55ccda7678d0ec5374f9d
4
+ data.tar.gz: 2793c75864c561a6d96833c7a171c687b0bda854
5
5
  SHA512:
6
- metadata.gz: 143053e6aa72ef607a876baa1059457e1db32a75e300448529feb3363ec991919b5c70bae3c147b6ac0b9a3095af862fb4c9dd8962bca0b2702943d650c48984
7
- data.tar.gz: ef07e3fe2b6c36d4a759d9564475881b43a9bb9319016440662e49b3e3de5aed64d912c5995a56b08abe4ddeb04d62f2cca09bf3ec3a3e9874e528e36297d7c1
6
+ metadata.gz: bd458037bec4658dd490234ca46ab75f82f3f74e40deb1e6a65d95eea6e3ddf49d3a7f0770885389830be92fed26124e3a66422fad584382fc21ec33ee9f0618
7
+ data.tar.gz: e0575ada72338c810ee9186104f75b1478d8518f7a91bd5e5ed2218282c1d5c52ea99988b69c8c0550197cbf04d5e2d89919d1a6a7175d21e261f5733572b707
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- disquo (0.3.0)
4
+ disquo (0.3.1)
5
5
  concurrent-ruby
6
6
  connection_pool
7
7
  disque
data/disquo.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "disquo"
5
- s.version = "0.3.0"
5
+ s.version = "0.3.1"
6
6
  s.platform = Gem::Platform::RUBY
7
7
 
8
8
  s.licenses = ["Apache-2.0"]
data/lib/disquo/worker.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'disquo'
2
- require 'concurrent'
3
2
  require 'concurrent/executor/fixed_thread_pool'
3
+ require 'concurrent/atomic/atomic_fixnum'
4
4
 
5
5
  class Disquo::Worker
6
6
  attr_reader :disque, :queues, :wait_time, :wait_count
@@ -10,19 +10,18 @@ class Disquo::Worker
10
10
  # @param [Hash] options
11
11
  # @option [Array<String>] :queues queues to watch. Default: ["default"]
12
12
  # @option [Integer] :concurrency the number of concurrent threads. Default: 10
13
- # @option [Numeric] :wait_time maximum time (in seconds) to block for when retrieving next batch. Default: 1s
14
- # @option [Integer] :wait_count the minimum number of jobs to wait for when retrieving next batch. Default: 100
15
- def initialize(disque, queues: [Disquo::DEFAULT_QUEUE], concurrency: 10, wait_time: 1, wait_count: 100)
13
+ # @option [Numeric] :wait_time maximum time (in seconds) to wait for jobs when retrieving next batch. Default: 1s
14
+ def initialize(disque, queues: [Disquo::DEFAULT_QUEUE], concurrency: 10, wait_time: 1)
16
15
  @disque = disque
17
16
  @queues = Array(queues)
18
17
  @threads = Concurrent::FixedThreadPool.new(concurrency)
18
+ @busy = Concurrent::AtomicFixnum.new
19
19
  @wait_time = wait_time
20
- @wait_count = wait_count
21
20
  end
22
21
 
23
22
  # Run starts the worker
24
23
  def run
25
- Disquo.logger.info "Starting worker - queues: #{queues.inspect}, concurrency: #{@threads.max_length}"
24
+ Disquo.logger.info "Worker starting - queues: #{queues.inspect}, concurrency: #{@threads.max_length}"
26
25
 
27
26
  begin
28
27
  run_cycle
@@ -30,14 +29,14 @@ class Disquo::Worker
30
29
  handle_exception(e)
31
30
  end until @stopped
32
31
 
32
+ Disquo.logger.info "Worker shutting down"
33
33
  @threads.shutdown
34
34
  end
35
35
 
36
36
  # Blocks until worker is stopped
37
37
  def wait(timeout = nil)
38
- Disquo.logger.info "Waiting for worker shutdown"
39
38
  @threads.wait_for_termination(timeout)
40
- Disquo.logger.info "Shutdown complete"
39
+ Disquo.logger.info "Worker shutdown complete"
41
40
  end
42
41
 
43
42
  # Stops the worker
@@ -50,57 +49,69 @@ class Disquo::Worker
50
49
  private
51
50
 
52
51
  def run_cycle
53
- jobs = next_batch
54
-
52
+ jobs = Array(next_batch)
55
53
  until @stopped || jobs.empty?
56
54
  job = jobs.shift
57
- perform(*job)
55
+ schedule(*job)
58
56
  end
59
57
  ensure
60
58
  requeue(jobs) unless jobs.nil? || jobs.empty?
61
59
  end
62
60
 
63
61
  def next_batch
62
+ count = @threads.max_length - @busy.value
63
+ if count < 1
64
+ sleep(wait_time.fdiv(2))
65
+ return
66
+ end
67
+
64
68
  jobs = disque.with do |cn|
65
- cn.fetch from: queues, timeout: (wait_time*1000).to_i, count: wait_count
69
+ cn.fetch from: queues, timeout: (wait_time*1000).to_i, count: count
66
70
  end
71
+
67
72
  @is_down = nil
68
- Array(jobs)
69
- rescue => e
70
- if !@is_down
71
- @is_down = true
72
- handle_exception(e, message: 'Error retrieving jobs:')
73
- end
74
- sleep(1)
75
- []
73
+ jobs
74
+ rescue Errno::ECONNREFUSED => e
75
+ handle_disque_exception e, message: "Failed to retrieve jobs:", notrace: true
76
+ nil
76
77
  end
77
78
 
78
- def perform(queue, job_id, payload)
79
+ def schedule(queue, job_id, payload)
80
+ @busy.increment
79
81
  @threads.post do
80
- thread_id = Thread.current.object_id.to_s(36)
81
- Disquo.logger.info { "Process #{payload} - thread: #{thread_id}, job: #{job_id}" }
82
-
83
82
  begin
84
- class_name, args = Disquo.load_job(payload)
85
-
86
- job = Object.const_get(class_name).new
87
- job.disque = disque
88
- job.queue = queue
89
- job.job_id = job_id
90
- job.perform(*args)
91
- rescue => e
92
- handle_exception e, message: "Error processing #{payload} - thread: #{thread_id}, job: #{job_id}:"
93
-
94
- disque.with {|cn| cn.call :nack, job_id }
95
- return
83
+ perform(queue, job_id, payload)
84
+ ensure
85
+ @busy.decrement
96
86
  end
87
+ end
88
+ end
97
89
 
98
- begin
99
- disque.with {|cn| cn.call :ackjob, job_id }
100
- rescue => e
101
- handle_exception e, message: "Error ACKing #{payload} - thread: #{thread_id}, job: #{job_id}:"
102
- return
103
- end
90
+ def perform(queue, job_id, payload)
91
+ thread_id = Thread.current.object_id.to_s(36)
92
+ Disquo.logger.info { "Process #{payload} - thread: #{thread_id}, job: #{job_id}" }
93
+
94
+ begin
95
+ class_name, args = Disquo.load_job(payload)
96
+
97
+ job = Object.const_get(class_name).new
98
+ job.disque = disque
99
+ job.queue = queue
100
+ job.job_id = job_id
101
+ job.perform(*args)
102
+ rescue => e
103
+ handle_exception e, message: "Error processing #{payload} - thread: #{thread_id}, job: #{job_id}:"
104
+
105
+ disque.with {|cn| cn.call :nack, job_id }
106
+ return
107
+ end
108
+
109
+ begin
110
+ disque.with {|cn| cn.call :ackjob, job_id }
111
+ @is_down = nil
112
+ rescue Errno::ECONNREFUSED => e
113
+ handle_disque_exception e, message: "Failed to ACK job #{job_id}:", notrace: true
114
+ retry unless @stopped
104
115
  end
105
116
  end
106
117
 
@@ -109,11 +120,19 @@ class Disquo::Worker
109
120
  disque.with {|cn| cn.call :enqueue, *ids }
110
121
  end
111
122
 
123
+ def handle_disque_exception(e, opts = {})
124
+ if !@is_down
125
+ @is_down = true
126
+ handle_exception(e, opts)
127
+ end
128
+ sleep(1)
129
+ end
130
+
112
131
  def handle_exception(e, opts = {})
113
132
  lines = [
114
133
  opts[:message],
115
134
  "#{e.class.name}: #{e.message}",
116
- e.backtrace
135
+ (opts[:notrace] ? nil : e.backtrace),
117
136
  ].compact.flatten
118
137
 
119
138
  Disquo.logger.error lines.join("\n")
@@ -3,11 +3,12 @@ require 'spec_helper'
3
3
  RSpec.describe Disquo::Worker do
4
4
 
5
5
  subject do
6
- described_class.new Disquo.connect, wait_time: 0.1, wait_count: 11, queues: Disquo::TEST::QUEUE
6
+ described_class.new Disquo.connect, wait_time: 0.1, queues: Disquo::TEST::QUEUE
7
7
  end
8
8
 
9
9
  it "should run/process/shutdown" do
10
10
  runner = Thread.new { subject.run }
11
+ runner.abort_on_exception = true
11
12
 
12
13
  # seed 200 jobs
13
14
  200.times {|n| TestJob.enqueue(n) }
@@ -33,12 +34,13 @@ RSpec.describe Disquo::Worker do
33
34
  queue: "__disquo_test__",
34
35
  )
35
36
  expect(Disquo::TEST::PERFORMED.last[:job_id]).to match(/^D\w+/)
37
+ expect(Disquo::TEST::PERFORMED.map {|e| e[:args].first }).to match_array(0..199)
36
38
  end
37
39
 
38
40
  def wait_for
39
41
  20.times do
40
42
  break if yield
41
- sleep(0.01)
43
+ sleep(0.1)
42
44
  end
43
45
  end
44
46
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: disquo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitrij Denissenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-23 00:00:00.000000000 Z
11
+ date: 2017-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: disque
@@ -87,6 +87,7 @@ executables:
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".gitignore"
90
91
  - ".travis.yml"
91
92
  - Gemfile
92
93
  - Gemfile.lock