shoryuken 2.1.1 → 3.0.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +5 -8
  3. data/.rubocop.yml +8 -2
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +48 -0
  6. data/README.md +20 -57
  7. data/Rakefile +0 -1
  8. data/bin/cli/base.rb +42 -0
  9. data/bin/cli/sqs.rb +188 -0
  10. data/bin/shoryuken +47 -9
  11. data/examples/default_worker.rb +1 -1
  12. data/lib/shoryuken/client.rb +3 -15
  13. data/lib/shoryuken/default_worker_registry.rb +9 -5
  14. data/lib/shoryuken/environment_loader.rb +11 -42
  15. data/lib/shoryuken/fetcher.rb +22 -53
  16. data/lib/shoryuken/launcher.rb +5 -29
  17. data/lib/shoryuken/manager.rb +72 -190
  18. data/lib/shoryuken/message.rb +4 -13
  19. data/lib/shoryuken/middleware/chain.rb +1 -18
  20. data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +13 -14
  21. data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +29 -20
  22. data/lib/shoryuken/polling.rb +204 -0
  23. data/lib/shoryuken/processor.rb +6 -14
  24. data/lib/shoryuken/queue.rb +1 -3
  25. data/lib/shoryuken/runner.rb +143 -0
  26. data/lib/shoryuken/util.rb +0 -8
  27. data/lib/shoryuken/version.rb +1 -1
  28. data/lib/shoryuken/worker.rb +1 -1
  29. data/lib/shoryuken.rb +77 -55
  30. data/shoryuken.gemspec +6 -6
  31. data/spec/integration/launcher_spec.rb +4 -3
  32. data/spec/shoryuken/client_spec.rb +2 -45
  33. data/spec/shoryuken/default_worker_registry_spec.rb +12 -10
  34. data/spec/shoryuken/environment_loader_spec.rb +34 -0
  35. data/spec/shoryuken/fetcher_spec.rb +18 -52
  36. data/spec/shoryuken/manager_spec.rb +56 -97
  37. data/spec/shoryuken/middleware/chain_spec.rb +0 -24
  38. data/spec/shoryuken/middleware/server/auto_delete_spec.rb +2 -2
  39. data/spec/shoryuken/middleware/server/auto_extend_visibility_spec.rb +7 -3
  40. data/spec/shoryuken/middleware/server/exponential_backoff_retry_spec.rb +56 -33
  41. data/spec/shoryuken/polling_spec.rb +239 -0
  42. data/spec/shoryuken/processor_spec.rb +5 -5
  43. data/spec/shoryuken/{cli_spec.rb → runner_spec.rb} +8 -22
  44. data/spec/shoryuken_spec.rb +13 -1
  45. data/spec/spec_helper.rb +3 -18
  46. data/test_workers/endless_interruptive_worker.rb +41 -0
  47. data/test_workers/endless_uninterruptive_worker.rb +44 -0
  48. metadata +32 -34
  49. data/lib/shoryuken/aws_config.rb +0 -64
  50. data/lib/shoryuken/cli.rb +0 -215
  51. data/lib/shoryuken/sns_arn.rb +0 -27
  52. data/lib/shoryuken/topic.rb +0 -17
  53. data/spec/shoryuken/sns_arn_spec.rb +0 -42
  54. data/spec/shoryuken/topic_spec.rb +0 -32
  55. data/spec/shoryuken_endpoint.yml +0 -6
@@ -28,10 +28,8 @@ module Shoryuken
28
28
  prefix_active_job_queue_names
29
29
  parse_queues
30
30
  require_workers
31
- initialize_aws
32
31
  validate_queues
33
32
  validate_workers
34
- patch_deprecated_workers
35
33
  end
36
34
 
37
35
  private
@@ -49,19 +47,9 @@ module Shoryuken
49
47
  YAML.load(ERB.new(IO.read(path)).result).deep_symbolize_keys
50
48
  end
51
49
 
52
- # DEPRECATED: Please use configure_server and configure_client in
53
- # https://github.com/phstc/shoryuken/blob/a81637d577b36c5cf245882733ea91a335b6602f/lib/shoryuken.rb#L82
54
- # Please delete this method afert next release (v2.0.12 or later)
55
- def initialize_aws
56
- unless Shoryuken.options[:aws].to_h.empty?
57
- Shoryuken.logger.warn { '[DEPRECATION] aws in shoryuken.yml is deprecated. Please use configure_server and configure_client in your initializer' }
58
- end
59
- Shoryuken::AwsConfig.setup(Shoryuken.options[:aws])
60
- end
61
-
62
50
  def initialize_logger
63
- Shoryuken::Logging.initialize_logger(options[:logfile]) if options[:logfile]
64
- Shoryuken.logger.level = Logger::DEBUG if options[:verbose]
51
+ Shoryuken::Logging.initialize_logger(Shoryuken.options[:logfile]) if Shoryuken.options[:logfile]
52
+ Shoryuken.logger.level = Logger::DEBUG if Shoryuken.options[:verbose]
65
53
  end
66
54
 
67
55
  def load_rails
@@ -83,12 +71,11 @@ module Shoryuken
83
71
  end
84
72
 
85
73
  def merge_cli_defined_queues
86
- cli_defined_queues = options.delete(:queues) || []
74
+ cli_defined_queues = options[:queues].to_a
87
75
 
88
76
  cli_defined_queues.each do |cli_defined_queue|
89
- Shoryuken.options[:queues].delete_if do |config_file_queue|
90
- config_file_queue[0] == cli_defined_queue[0]
91
- end
77
+ # CLI defined queues override config_file defined queues
78
+ Shoryuken.options[:queues].delete_if { |config_file_queue| config_file_queue[0] == cli_defined_queue[0] }
92
79
 
93
80
  Shoryuken.options[:queues] << cli_defined_queue
94
81
  end
@@ -110,7 +97,7 @@ module Shoryuken
110
97
  end
111
98
 
112
99
  def parse_queue(queue, weight = nil)
113
- [weight.to_i, 1].max.times { Shoryuken.queues << queue }
100
+ Shoryuken.add_queue(queue, [weight.to_i, 1].max)
114
101
  end
115
102
 
116
103
  def parse_queues
@@ -119,24 +106,6 @@ module Shoryuken
119
106
  end
120
107
  end
121
108
 
122
- def patch_deprecated_workers
123
- Shoryuken.worker_registry.queues.each do |queue|
124
- Shoryuken.worker_registry.workers(queue).each do |worker_class|
125
- if worker_class.instance_method(:perform).arity == 1
126
- Shoryuken.logger.warn { "[DEPRECATION] #{worker_class.name}#perform(sqs_msg) is deprecated. Please use #{worker_class.name}#perform(sqs_msg, body)" }
127
-
128
- worker_class.class_eval do
129
- alias_method :deprecated_perform, :perform
130
-
131
- def perform(sqs_msg, body = nil)
132
- deprecated_perform(sqs_msg)
133
- end
134
- end
135
- end
136
- end
137
- end
138
- end
139
-
140
109
  def require_workers
141
110
  required = Shoryuken.options[:require]
142
111
 
@@ -156,7 +125,7 @@ module Shoryuken
156
125
 
157
126
  Shoryuken.queues.uniq.each do |queue|
158
127
  begin
159
- Shoryuken::Client.queues queue
128
+ Shoryuken::Client.queues(queue)
160
129
  rescue Aws::SQS::Errors::NonExistentQueue
161
130
  non_existent_queues << queue
162
131
  end
@@ -166,13 +135,13 @@ module Shoryuken
166
135
  end
167
136
 
168
137
  def validate_workers
138
+ return if defined?(::ActiveJob)
139
+
169
140
  all_queues = Shoryuken.queues
170
141
  queues_with_workers = Shoryuken.worker_registry.queues
171
142
 
172
- unless defined?(::ActiveJob)
173
- (all_queues - queues_with_workers).each do |queue|
174
- Shoryuken.logger.warn { "No worker supplied for '#{queue}'" }
175
- end
143
+ (all_queues - queues_with_workers).each do |queue|
144
+ Shoryuken.logger.warn { "No worker supplied for '#{queue}'" }
176
145
  end
177
146
  end
178
147
  end
@@ -1,73 +1,42 @@
1
1
  module Shoryuken
2
2
  class Fetcher
3
- include Celluloid
4
3
  include Util
5
4
 
6
5
  FETCH_LIMIT = 10
7
6
 
8
- def initialize(manager)
9
- @manager = manager
7
+ def fetch(queue, available_processors)
8
+ started_at = Time.now
9
+
10
+ logger.debug { "Looking for new messages in '#{queue}'" }
11
+
12
+ begin
13
+ limit = available_processors > FETCH_LIMIT ? FETCH_LIMIT : available_processors
14
+
15
+ sqs_msgs = Array(receive_messages(queue, limit))
16
+ logger.info { "Found #{sqs_msgs.size} messages for '#{queue.name}'" } unless sqs_msgs.empty?
17
+ logger.debug { "Fetcher for '#{queue}' completed in #{elapsed(started_at)} ms" }
18
+ sqs_msgs
19
+ rescue => ex
20
+ logger.error { "Error fetching message: #{ex}" }
21
+ logger.error { ex.backtrace.first }
22
+ []
23
+ end
10
24
  end
11
25
 
26
+ private
27
+
12
28
  def receive_messages(queue, limit)
13
29
  # AWS limits the batch size by 10
14
30
  limit = limit > FETCH_LIMIT ? FETCH_LIMIT : limit
15
31
 
16
- options = (Shoryuken::AwsConfig.options[:receive_message] || {}).dup
32
+ options = Shoryuken.sqs_client_receive_message_opts.to_h.dup
17
33
  options[:max_number_of_messages] = limit
18
34
  options[:message_attribute_names] = %w(All)
19
35
  options[:attribute_names] = %w(All)
20
36
 
21
- Shoryuken::Client.queues(queue).receive_messages options
22
- end
23
-
24
- def fetch(queue, available_processors)
25
- watchdog('Fetcher#fetch died') do
26
- started_at = Time.now
27
-
28
- logger.debug { "Looking for new messages in '#{queue}'" }
29
-
30
- begin
31
- batch = Shoryuken.worker_registry.batch_receive_messages?(queue)
32
- limit = batch ? FETCH_LIMIT : available_processors
33
-
34
- if (sqs_msgs = Array(receive_messages(queue, limit))).any?
35
- logger.debug { "Found #{sqs_msgs.size} messages for '#{queue}'" }
36
-
37
- if batch
38
- @manager.async.assign(queue, patch_sqs_msgs!(sqs_msgs))
39
- else
40
- sqs_msgs.each { |sqs_msg| @manager.async.assign(queue, sqs_msg) }
41
- end
42
-
43
- @manager.async.rebalance_queue_weight!(queue)
44
- else
45
- logger.debug { "No message found for '#{queue}'" }
46
-
47
- @manager.async.pause_queue!(queue)
48
- end
49
-
50
- logger.debug { "Fetcher for '#{queue}' completed in #{elapsed(started_at)} ms" }
51
- rescue => ex
52
- logger.error { "Error fetching message: #{ex}" }
53
- logger.error { ex.backtrace.first }
54
- end
55
-
56
- @manager.async.dispatch
57
- end
58
-
59
- end
60
-
61
- private
62
-
63
- def patch_sqs_msgs!(sqs_msgs)
64
- sqs_msgs.instance_eval do
65
- def message_id
66
- "batch-with-#{size}-messages"
67
- end
68
- end
37
+ options.merge!(queue.options)
69
38
 
70
- sqs_msgs
39
+ Shoryuken::Client.queues(queue.name).receive_messages(options)
71
40
  end
72
41
  end
73
42
  end
@@ -1,43 +1,19 @@
1
1
  module Shoryuken
2
2
  class Launcher
3
- include Celluloid
4
3
  include Util
5
4
 
6
- trap_exit :actor_died
7
-
8
- attr_accessor :manager
9
-
10
5
  def initialize
11
- @condvar = Celluloid::Condition.new
12
- @manager = Shoryuken::Manager.new_link(@condvar)
13
- @fetcher = Shoryuken::Fetcher.new_link(manager)
14
-
15
- @done = false
16
-
17
- manager.fetcher = @fetcher
6
+ @manager = Shoryuken::Manager.new(Shoryuken::Fetcher.new,
7
+ Shoryuken.options[:polling_strategy].new(Shoryuken.queues))
18
8
  end
19
9
 
20
10
  def stop(options = {})
21
- watchdog('Launcher#stop') do
22
- @done = true
23
- @fetcher.terminate if @fetcher.alive?
24
-
25
- manager.async.stop(shutdown: !!options[:shutdown], timeout: Shoryuken.options[:timeout])
26
- @condvar.wait
27
- manager.terminate
28
- end
11
+ @manager.stop(shutdown: !options[:shutdown].nil?,
12
+ timeout: Shoryuken.options[:timeout])
29
13
  end
30
14
 
31
15
  def run
32
- watchdog('Launcher#run') do
33
- manager.async.start
34
- end
35
- end
36
-
37
- def actor_died(actor, reason)
38
- return if @done
39
- logger.warn { "Shoryuken died due to the following error, cannot recover, process exiting: #{reason}" }
40
- exit 1
16
+ @manager.start
41
17
  end
42
18
  end
43
19
  end
@@ -1,251 +1,133 @@
1
- require 'shoryuken/processor'
2
- require 'shoryuken/fetcher'
3
-
4
1
  module Shoryuken
5
2
  class Manager
6
- include Celluloid
7
3
  include Util
8
4
 
9
- attr_accessor :fetcher
5
+ BATCH_LIMIT = 10
6
+ HEARTBEAT_INTERVAL = 0.1
10
7
 
11
- trap_exit :processor_died
8
+ def initialize(fetcher, polling_strategy)
9
+ @count = Shoryuken.options.fetch(:concurrency, 25)
12
10
 
13
- def initialize(condvar)
14
- @count = Shoryuken.options[:concurrency] || 25
15
11
  raise(ArgumentError, "Concurrency value #{@count} is invalid, it needs to be a positive number") unless @count > 0
12
+
16
13
  @queues = Shoryuken.queues.dup.uniq
17
- @finished = condvar
18
14
 
19
- @done = false
15
+ @done = Concurrent::AtomicBoolean.new(false)
16
+ @dispatching = Concurrent::AtomicBoolean.new(false)
17
+
18
+ @fetcher = fetcher
19
+ @polling_strategy = polling_strategy
20
20
 
21
- @busy = []
22
- @ready = @count.times.map { build_processor }
23
- @threads = {}
21
+ @heartbeat = Concurrent::TimerTask.new(run_now: true,
22
+ execution_interval: HEARTBEAT_INTERVAL,
23
+ timeout_interval: 60) { dispatch }
24
+
25
+ @pool = Concurrent::FixedThreadPool.new(@count, max_queue: @count)
24
26
  end
25
27
 
26
28
  def start
27
29
  logger.info { 'Starting' }
28
30
 
29
- dispatch
31
+ @heartbeat.execute
30
32
  end
31
33
 
32
34
  def stop(options = {})
33
- watchdog('Manager#stop died') do
34
- @done = true
35
-
36
- if (callback = Shoryuken.stop_callback)
37
- logger.info { 'Calling Shoryuken.on_stop block' }
38
- callback.call
39
- end
40
-
41
- fire_event(:shutdown, true)
42
-
43
- @fetcher.terminate if @fetcher.alive?
44
-
45
- logger.info { "Shutting down #{@ready.size} quiet workers" }
35
+ @done.make_true
46
36
 
47
- @ready.each do |processor|
48
- processor.terminate if processor.alive?
49
- end
50
- @ready.clear
51
-
52
- return after(0) { @finished.signal } if @busy.empty?
53
-
54
- if options[:shutdown]
55
- hard_shutdown_in(options[:timeout])
56
- else
57
- soft_shutdown(options[:timeout])
58
- end
37
+ if (callback = Shoryuken.stop_callback)
38
+ logger.info { 'Calling Shoryuken.on_stop block' }
39
+ callback.call
59
40
  end
60
- end
61
41
 
62
- def processor_done(queue, processor)
63
- watchdog('Manager#processor_done died') do
64
- logger.debug { "Process done for '#{queue}'" }
42
+ fire_event(:shutdown, true)
65
43
 
66
- @threads.delete(processor.object_id)
67
- @busy.delete processor
44
+ logger.info { 'Shutting down workers' }
68
45
 
69
- if stopped?
70
- processor.terminate if processor.alive?
71
- return after(0) { @finished.signal } if @busy.empty?
72
- else
73
- @ready << processor
74
- end
75
- end
76
- end
46
+ @heartbeat.kill
77
47
 
78
- def processor_died(processor, reason)
79
- watchdog("Manager#processor_died died") do
80
- logger.error { "Process died, reason: #{reason}" }
81
-
82
- @threads.delete(processor.object_id)
83
- @busy.delete processor
84
-
85
- if stopped?
86
- return after(0) { @finished.signal } if @busy.empty?
87
- else
88
- @ready << build_processor
89
- end
90
- end
91
- end
92
-
93
- def stopped?
94
- @done
95
- end
96
-
97
- def assign(queue, sqs_msg)
98
- watchdog('Manager#assign died') do
99
- logger.debug { "Assigning #{sqs_msg.message_id}" }
100
-
101
- processor = @ready.pop
102
- @busy << processor
103
-
104
- processor.async.process(queue, sqs_msg)
105
- end
106
- end
107
-
108
- def rebalance_queue_weight!(queue)
109
- watchdog('Manager#rebalance_queue_weight! died') do
110
- if (original = original_queue_weight(queue)) > (current = current_queue_weight(queue))
111
- logger.info { "Increasing '#{queue}' weight to #{current + 1}, max: #{original}" }
112
-
113
- @queues << queue
114
- end
48
+ if options[:shutdown]
49
+ hard_shutdown_in(options[:timeout])
50
+ else
51
+ soft_shutdown
115
52
  end
116
53
  end
117
54
 
118
- def pause_queue!(queue)
119
- return if !@queues.include?(queue) || Shoryuken.options[:delay].to_f <= 0
120
-
121
- logger.debug { "Pausing '#{queue}' for #{Shoryuken.options[:delay].to_f} seconds, because it's empty" }
122
-
123
- @queues.delete(queue)
124
-
125
- after(Shoryuken.options[:delay].to_f) { async.restart_queue!(queue) }
55
+ def processor_done(queue)
56
+ logger.debug { "Process done for '#{queue}'" }
126
57
  end
127
58
 
59
+ private
128
60
 
129
61
  def dispatch
130
- return if stopped?
62
+ return if @done.true?
63
+ return unless @dispatching.make_true
131
64
 
132
- logger.debug { "Ready: #{@ready.size}, Busy: #{@busy.size}, Active Queues: #{unparse_queues(@queues)}" }
65
+ return if ready.zero?
66
+ return unless (queue = @polling_strategy.next_queue)
133
67
 
134
- if @ready.empty?
135
- logger.debug { 'Pausing fetcher, because all processors are busy' }
136
-
137
- dispatch_later
138
- return
139
- end
140
-
141
- if (queue = next_queue)
142
- @fetcher.async.fetch(queue, @ready.size)
143
- else
144
- logger.debug { 'Pausing fetcher, because all queues are paused' }
68
+ logger.debug { "Ready: #{ready}, Busy: #{busy}, Active Queues: #{@polling_strategy.active_queues}" }
145
69
 
146
- @fetcher_paused = true
147
- end
148
- end
149
-
150
- def real_thread(proxy_id, thr)
151
- @threads[proxy_id] = thr
70
+ batched_queue?(queue) ? dispatch_batch(queue) : dispatch_single_messages(queue)
71
+ ensure
72
+ @dispatching.make_false
152
73
  end
153
74
 
154
- private
155
-
156
- def dispatch_later
157
- @_dispatch_timer ||= after(1) do
158
- @_dispatch_timer = nil
159
- dispatch
160
- end
75
+ def busy
76
+ @count - ready
161
77
  end
162
78
 
163
- def build_processor
164
- processor = Processor.new_link(current_actor)
165
- processor.proxy_id = processor.object_id
166
- processor
79
+ def ready
80
+ @pool.remaining_capacity
167
81
  end
168
82
 
169
- def restart_queue!(queue)
170
- return if stopped?
171
-
172
- unless @queues.include? queue
173
- logger.debug { "Restarting '#{queue}'" }
174
-
175
- @queues << queue
176
-
177
- if @fetcher_paused
178
- logger.debug { 'Restarting fetcher' }
179
-
180
- @fetcher_paused = false
83
+ def assign(queue, sqs_msg)
84
+ logger.debug { "Assigning #{sqs_msg.message_id}" }
181
85
 
182
- dispatch
183
- end
184
- end
86
+ @pool.post { Processor.new(self).process(queue, sqs_msg) }
185
87
  end
186
88
 
187
- def current_queue_weight(queue)
188
- queue_weight(@queues, queue)
89
+ def dispatch_batch(queue)
90
+ batch = @fetcher.fetch(queue, BATCH_LIMIT)
91
+ @polling_strategy.messages_found(queue.name, batch.size)
92
+ assign(queue.name, patch_batch!(batch))
189
93
  end
190
94
 
191
- def original_queue_weight(queue)
192
- queue_weight(Shoryuken.queues, queue)
95
+ def dispatch_single_messages(queue)
96
+ messages = @fetcher.fetch(queue, ready)
97
+ @polling_strategy.messages_found(queue.name, messages.size)
98
+ messages.each { |message| assign(queue.name, message) }
193
99
  end
194
100
 
195
- def queue_weight(queues, queue)
196
- queues.count { |q| q == queue }
101
+ def batched_queue?(queue)
102
+ Shoryuken.worker_registry.batch_receive_messages?(queue.name)
197
103
  end
198
104
 
199
- def next_queue
200
- return nil if @queues.empty?
201
-
202
- # get/remove the first queue in the list
203
- queue = @queues.shift
204
-
205
- unless defined?(::ActiveJob) || !Shoryuken.worker_registry.workers(queue).empty?
206
- # when no worker registered pause the queue to avoid endless recursion
207
- logger.debug { "Pausing '#{queue}' for #{Shoryuken.options[:delay].to_f} seconds, because no workers registered" }
208
-
209
- after(Shoryuken.options[:delay].to_f) { async.restart_queue!(queue) }
105
+ def soft_shutdown
106
+ @pool.shutdown
107
+ @pool.wait_for_termination
108
+ end
210
109
 
211
- return next_queue
110
+ def hard_shutdown_in(delay)
111
+ if busy > 0
112
+ logger.info { "Pausing up to #{delay} seconds to allow workers to finish..." }
212
113
  end
213
114
 
214
- # add queue back to the end of the list
215
- @queues << queue
216
-
217
- queue
218
- end
115
+ @pool.shutdown
219
116
 
220
- def soft_shutdown(delay)
221
- logger.info { "Waiting for #{@busy.size} busy workers" }
117
+ return if @pool.wait_for_termination(delay)
222
118
 
223
- if @busy.size > 0
224
- after(delay) { soft_shutdown(delay) }
225
- else
226
- @finished.signal
227
- end
119
+ logger.info { "Hard shutting down #{busy} busy workers" }
120
+ @pool.kill
228
121
  end
229
122
 
230
- def hard_shutdown_in(delay)
231
- logger.info { "Waiting for #{@busy.size} busy workers" }
232
- logger.info { "Pausing up to #{delay} seconds to allow workers to finish..." }
233
-
234
- after(delay) do
235
- watchdog('Manager#hard_shutdown_in died') do
236
- if @busy.size > 0
237
- logger.info { "Hard shutting down #{@busy.size} busy workers" }
238
-
239
- @busy.each do |processor|
240
- if processor.alive? && t = @threads.delete(processor.object_id)
241
- t.raise Shutdown
242
- end
243
- end
244
- end
245
-
246
- @finished.signal
123
+ def patch_batch!(sqs_msgs)
124
+ sqs_msgs.instance_eval do
125
+ def message_id
126
+ "batch-with-#{size}-messages"
247
127
  end
248
128
  end
129
+
130
+ sqs_msgs
249
131
  end
250
132
  end
251
133
  end
@@ -3,19 +3,10 @@ module Shoryuken
3
3
  attr_accessor :client, :queue_url, :queue_name, :data
4
4
 
5
5
  def initialize(client, queue, data)
6
- self.client = client
7
- self.data = data
8
-
9
- if queue.is_a?(Shoryuken::Queue)
10
- self.queue_url = queue.url
11
- self.queue_name = queue.name
12
- else
13
- # TODO: Remove next major release
14
- Shoryuken.logger.warn do
15
- '[DEPRECATION] Passing a queue url into Shoryuken::Message is deprecated, please pass the queue itself'
16
- end
17
- self.queue_url = queue
18
- end
6
+ self.client = client
7
+ self.data = data
8
+ self.queue_url = queue.url
9
+ self.queue_name = queue.name
19
10
  end
20
11
 
21
12
  def delete
@@ -102,32 +102,15 @@ module Shoryuken
102
102
 
103
103
  class Entry
104
104
  attr_reader :klass
105
+
105
106
  def initialize(klass, *args)
106
107
  @klass = klass
107
108
  @args = args
108
-
109
- patch_deprecated_middleware!(klass)
110
109
  end
111
110
 
112
111
  def make_new
113
112
  @klass.new(*@args)
114
113
  end
115
-
116
- private
117
-
118
- def patch_deprecated_middleware!(klass)
119
- if klass.instance_method(:call).arity == 3
120
- Shoryuken.logger.warn { "[DEPRECATION] #{klass.name}#call(worker_instance, queue, sqs_msg) is deprecated. Please use #{klass.name}#call(worker_instance, queue, sqs_msg, body)" }
121
-
122
- klass.class_eval do
123
- alias_method :deprecated_call, :call
124
-
125
- def call(worker_instance, queue, sqs_msg, body = nil, &block)
126
- deprecated_call(worker_instance, queue, sqs_msg, &block)
127
- end
128
- end
129
- end
130
- end
131
114
  end
132
115
  end
133
116
  end
@@ -1,33 +1,32 @@
1
- require 'celluloid/current' unless defined?(Celluloid)
2
-
3
1
  module Shoryuken
4
2
  module Middleware
5
3
  module Server
6
4
  class AutoExtendVisibility
5
+ include Util
6
+
7
7
  EXTEND_UPFRONT_SECONDS = 5
8
8
 
9
9
  def call(worker, queue, sqs_msg, body)
10
- timer = auto_visibility_timer(worker, queue, sqs_msg, body)
11
- begin
12
- yield
13
- ensure
14
- if timer
15
- timer.cancel
16
- @visibility_extender.terminate
17
- end
10
+ if sqs_msg.is_a?(Array)
11
+ logger.warn { "Auto extend visibility isn't supported for batch workers" }
12
+ return yield
18
13
  end
14
+
15
+ timer = auto_visibility_timer(worker, queue, sqs_msg, body)
16
+ yield
17
+ ensure
18
+ timer.kill if timer
19
19
  end
20
20
 
21
21
  private
22
22
 
23
23
  class MessageVisibilityExtender
24
- include Celluloid
25
24
  include Util
26
25
 
27
26
  def auto_extend(worker, queue, sqs_msg, body)
28
27
  queue_visibility_timeout = Shoryuken::Client.queues(queue).visibility_timeout
29
28
 
30
- every(queue_visibility_timeout - EXTEND_UPFRONT_SECONDS) do
29
+ Concurrent::TimerTask.new(execution_interval: queue_visibility_timeout - EXTEND_UPFRONT_SECONDS) do
31
30
  begin
32
31
  logger.debug do
33
32
  "Extending message #{worker_name(worker.class, sqs_msg, body)}/#{queue}/#{sqs_msg.message_id} " \
@@ -48,8 +47,8 @@ module Shoryuken
48
47
 
49
48
  def auto_visibility_timer(worker, queue, sqs_msg, body)
50
49
  return unless worker.class.auto_visibility_timeout?
51
- @visibility_extender = MessageVisibilityExtender.new_link
52
- @visibility_extender.auto_extend(worker, queue, sqs_msg, body)
50
+
51
+ MessageVisibilityExtender.new.auto_extend(worker, queue, sqs_msg, body).tap(&:execute)
53
52
  end
54
53
  end
55
54
  end