shoryuken 3.0.6 → 4.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +90 -24
  3. data/.travis.yml +17 -5
  4. data/CHANGELOG.md +265 -62
  5. data/Gemfile +9 -1
  6. data/Gemfile.aws-sdk-core-v2 +13 -0
  7. data/README.md +19 -113
  8. data/Rakefile +1 -1
  9. data/bin/cli/base.rb +0 -3
  10. data/bin/cli/sqs.rb +42 -16
  11. data/bin/shoryuken +4 -9
  12. data/examples/bootstrap_queues.rb +3 -3
  13. data/examples/default_worker.rb +2 -2
  14. data/lib/shoryuken/body_parser.rb +27 -0
  15. data/lib/shoryuken/client.rb +6 -2
  16. data/lib/shoryuken/core_ext.rb +1 -1
  17. data/lib/shoryuken/default_worker_registry.rb +2 -2
  18. data/lib/shoryuken/environment_loader.rb +60 -24
  19. data/lib/shoryuken/extensions/active_job_adapter.rb +21 -11
  20. data/lib/shoryuken/fetcher.rb +58 -19
  21. data/lib/shoryuken/launcher.rb +70 -7
  22. data/lib/shoryuken/logging.rb +1 -6
  23. data/lib/shoryuken/manager.rb +50 -80
  24. data/lib/shoryuken/middleware/chain.rb +4 -0
  25. data/lib/shoryuken/middleware/server/active_record.rb +1 -1
  26. data/lib/shoryuken/middleware/server/auto_delete.rb +4 -9
  27. data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +6 -9
  28. data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +9 -3
  29. data/lib/shoryuken/middleware/server/timing.rb +12 -16
  30. data/lib/shoryuken/options.rb +225 -0
  31. data/lib/shoryuken/polling/base.rb +67 -0
  32. data/lib/shoryuken/polling/strict_priority.rb +77 -0
  33. data/lib/shoryuken/polling/weighted_round_robin.rb +66 -0
  34. data/lib/shoryuken/processor.rb +30 -39
  35. data/lib/shoryuken/queue.rb +41 -10
  36. data/lib/shoryuken/runner.rb +13 -17
  37. data/lib/shoryuken/util.rb +3 -3
  38. data/lib/shoryuken/version.rb +1 -1
  39. data/lib/shoryuken/worker/default_executor.rb +33 -0
  40. data/lib/shoryuken/worker/inline_executor.rb +37 -0
  41. data/lib/shoryuken/worker.rb +76 -31
  42. data/lib/shoryuken/worker_registry.rb +4 -4
  43. data/lib/shoryuken.rb +54 -173
  44. data/shoryuken.gemspec +6 -6
  45. data/spec/integration/launcher_spec.rb +14 -8
  46. data/spec/shoryuken/body_parser_spec.rb +89 -0
  47. data/spec/shoryuken/client_spec.rb +1 -1
  48. data/spec/shoryuken/core_ext_spec.rb +6 -6
  49. data/spec/shoryuken/default_worker_registry_spec.rb +2 -4
  50. data/spec/shoryuken/environment_loader_spec.rb +32 -12
  51. data/spec/shoryuken/extensions/active_job_adapter_spec.rb +64 -0
  52. data/spec/shoryuken/fetcher_spec.rb +101 -18
  53. data/spec/shoryuken/manager_spec.rb +54 -26
  54. data/spec/shoryuken/middleware/chain_spec.rb +17 -5
  55. data/spec/shoryuken/middleware/server/auto_delete_spec.rb +9 -7
  56. data/spec/shoryuken/middleware/server/auto_extend_visibility_spec.rb +4 -4
  57. data/spec/shoryuken/middleware/server/exponential_backoff_retry_spec.rb +6 -4
  58. data/spec/shoryuken/middleware/server/timing_spec.rb +5 -3
  59. data/spec/shoryuken/options_spec.rb +180 -0
  60. data/spec/shoryuken/{polling_spec.rb → polling/strict_priority_spec.rb} +2 -101
  61. data/spec/shoryuken/polling/weighted_round_robin_spec.rb +99 -0
  62. data/spec/shoryuken/processor_spec.rb +26 -127
  63. data/spec/shoryuken/queue_spec.rb +115 -41
  64. data/spec/shoryuken/runner_spec.rb +3 -4
  65. data/spec/shoryuken/util_spec.rb +24 -0
  66. data/spec/shoryuken/worker/default_executor_spec.rb +105 -0
  67. data/spec/shoryuken/worker/inline_executor_spec.rb +49 -0
  68. data/spec/shoryuken/worker_spec.rb +35 -96
  69. data/spec/shoryuken_spec.rb +0 -59
  70. data/spec/spec_helper.rb +14 -3
  71. data/test_workers/endless_interruptive_worker.rb +2 -2
  72. data/test_workers/endless_uninterruptive_worker.rb +4 -4
  73. metadata +31 -12
  74. data/lib/shoryuken/polling.rb +0 -204
@@ -1,3 +1,3 @@
1
1
  module Shoryuken
2
- VERSION = '3.0.6'.freeze
2
+ VERSION = '4.0.0'.freeze
3
3
  end
@@ -0,0 +1,33 @@
1
+ module Shoryuken
2
+ module Worker
3
+ class DefaultExecutor
4
+ class << self
5
+ def perform_async(worker_class, body, options = {})
6
+ options[:message_attributes] ||= {}
7
+ options[:message_attributes]['shoryuken_class'] = {
8
+ string_value: worker_class.to_s,
9
+ data_type: 'String'
10
+ }
11
+
12
+ options[:message_body] = body
13
+
14
+ queue = options.delete(:queue) || worker_class.get_shoryuken_options['queue']
15
+
16
+ Shoryuken::Client.queues(queue).send_message(options)
17
+ end
18
+
19
+ def perform_in(worker_class, interval, body, options = {})
20
+ interval = interval.to_f
21
+ now = Time.now.to_f
22
+ ts = (interval < 1_000_000_000 ? (now + interval).to_f : interval)
23
+
24
+ delay = (ts - now).ceil
25
+
26
+ raise 'The maximum allowed delay is 15 minutes' if delay > 15 * 60
27
+
28
+ worker_class.perform_async(body, options.merge(delay_seconds: delay))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ module Shoryuken
2
+ module Worker
3
+ class InlineExecutor
4
+ class << self
5
+ def perform_async(worker_class, body, _options = {})
6
+ body = JSON.dump(body) if body.is_a?(Hash)
7
+
8
+ sqs_msg = OpenStruct.new(
9
+ body: body,
10
+ attributes: nil,
11
+ md5_of_body: nil,
12
+ md5_of_message_attributes: nil,
13
+ message_attributes: nil,
14
+ message_id: nil,
15
+ receipt_handle: nil,
16
+ delete: nil
17
+ )
18
+
19
+ call(worker_class, sqs_msg)
20
+ end
21
+
22
+ def perform_in(worker_class, _interval, body, options = {})
23
+ worker_class.perform_async(body, options)
24
+ end
25
+
26
+ private
27
+
28
+ def call(worker_class, sqs_msg)
29
+ parsed_body = BodyParser.parse(worker_class, sqs_msg)
30
+ batch = worker_class.shoryuken_options_hash['batch']
31
+ args = batch ? [[sqs_msg], [parsed_body]] : [sqs_msg, parsed_body]
32
+ worker_class.new.perform(*args)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -2,33 +2,16 @@ module Shoryuken
2
2
  module Worker
3
3
  def self.included(base)
4
4
  base.extend(ClassMethods)
5
+ base.shoryuken_class_attribute :shoryuken_options_hash
5
6
  end
6
7
 
7
8
  module ClassMethods
8
9
  def perform_async(body, options = {})
9
- options[:message_attributes] ||= {}
10
- options[:message_attributes]['shoryuken_class'] = {
11
- string_value: self.to_s,
12
- data_type: 'String'
13
- }
14
-
15
- options[:message_body] = body
16
-
17
- queue = options.delete(:queue) || get_shoryuken_options['queue']
18
-
19
- Shoryuken::Client.queues(queue).send_message(options)
10
+ Shoryuken.worker_executor.perform_async(self, body, options)
20
11
  end
21
12
 
22
13
  def perform_in(interval, body, options = {})
23
- interval = interval.to_f
24
- now = Time.now.to_f
25
- ts = (interval < 1_000_000_000 ? (now + interval).to_f : interval)
26
-
27
- delay = (ts - now).ceil
28
-
29
- raise 'The maximum allowed delay is 15 minutes' if delay > 15 * 60
30
-
31
- perform_async(body, options.merge(delay_seconds: delay))
14
+ Shoryuken.worker_executor.perform_in(self, interval, body, options)
32
15
  end
33
16
 
34
17
  alias_method :perform_at, :perform_in
@@ -40,7 +23,7 @@ module Shoryuken
40
23
  end
41
24
 
42
25
  def shoryuken_options(opts = {})
43
- @shoryuken_options = get_shoryuken_options.merge(stringify_keys(opts || {}))
26
+ self.shoryuken_options_hash = get_shoryuken_options.merge(stringify_keys(opts || {}))
44
27
  normalize_worker_queue!
45
28
  end
46
29
 
@@ -48,34 +31,96 @@ module Shoryuken
48
31
  !!get_shoryuken_options['auto_visibility_timeout']
49
32
  end
50
33
 
34
+ def exponential_backoff?
35
+ !!get_shoryuken_options['retry_intervals']
36
+ end
37
+
38
+ def auto_delete?
39
+ !!(get_shoryuken_options['delete'] || get_shoryuken_options['auto_delete'])
40
+ end
41
+
51
42
  def get_shoryuken_options # :nodoc:
52
- @shoryuken_options || Shoryuken.default_worker_options
43
+ shoryuken_options_hash || Shoryuken.default_worker_options
53
44
  end
54
45
 
55
46
  def stringify_keys(hash) # :nodoc:
56
- hash.keys.each do |key|
57
- hash[key.to_s] = hash.delete(key)
47
+ new_hash = {}
48
+ hash.each { |key, value| new_hash[key.to_s] = value }
49
+ new_hash
50
+ end
51
+
52
+ def shoryuken_class_attribute(*attrs) # :nodoc:
53
+ attrs.each do |name|
54
+ singleton_class.instance_eval do
55
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
56
+ end
57
+ define_singleton_method(name) { nil }
58
+
59
+ ivar = "@#{name}"
60
+
61
+ singleton_class.instance_eval do
62
+ m = "#{name}="
63
+ undef_method(m) if method_defined?(m) || private_method_defined?(m)
64
+ end
65
+
66
+ define_singleton_method("#{name}=") do |val|
67
+ singleton_class.class_eval do
68
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
69
+ define_method(name) { val }
70
+ end
71
+
72
+ # singleton? backwards compatibility for ruby < 2.1
73
+ singleton_klass = respond_to?(:singleton?) ? singleton? : self != ancestors.first
74
+
75
+ if singleton_klass
76
+ class_eval do
77
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
78
+ define_method(name) do
79
+ if instance_variable_defined? ivar
80
+ instance_variable_get ivar
81
+ else
82
+ singleton_class.send name
83
+ end
84
+ end
85
+ end
86
+ end
87
+ val
88
+ end
89
+
90
+ # instance reader
91
+ undef_method(name) if method_defined?(name) || private_method_defined?(name)
92
+ define_method(name) do
93
+ if instance_variable_defined?(ivar)
94
+ instance_variable_get ivar
95
+ else
96
+ self.class.public_send name
97
+ end
98
+ end
99
+
100
+ # instance writer
101
+ m = "#{name}="
102
+ undef_method(m) if method_defined?(m) || private_method_defined?(m)
103
+ attr_writer name
58
104
  end
59
- hash
60
105
  end
61
106
 
62
107
  private
63
108
 
64
109
  def normalize_worker_queue!
65
- queue = @shoryuken_options['queue']
110
+ queue = shoryuken_options_hash['queue']
66
111
  if queue.respond_to?(:call)
67
112
  queue = queue.call
68
- @shoryuken_options['queue'] = queue
113
+ shoryuken_options_hash['queue'] = queue
69
114
  end
70
115
 
71
- case @shoryuken_options['queue']
116
+ case shoryuken_options_hash['queue']
72
117
  when Array
73
- @shoryuken_options['queue'].map!(&:to_s)
118
+ shoryuken_options_hash['queue'].map!(&:to_s)
74
119
  when Symbol
75
- @shoryuken_options['queue'] = @shoryuken_options['queue'].to_s
120
+ shoryuken_options_hash['queue'] = shoryuken_options_hash['queue'].to_s
76
121
  end
77
122
 
78
- [@shoryuken_options['queue']].flatten.compact.each(&method(:register_worker))
123
+ [shoryuken_options_hash['queue']].flatten.compact.each(&method(:register_worker))
79
124
  end
80
125
 
81
126
  def register_worker(queue)
@@ -1,6 +1,6 @@
1
1
  module Shoryuken
2
2
  class WorkerRegistry
3
- def batch_receive_messages?(queue)
3
+ def batch_receive_messages?(_queue)
4
4
  # true if the workers for queue support batch processing of messages
5
5
  fail NotImplementedError
6
6
  end
@@ -10,7 +10,7 @@ module Shoryuken
10
10
  fail NotImplementedError
11
11
  end
12
12
 
13
- def fetch_worker(queue, message)
13
+ def fetch_worker(_queue, _message)
14
14
  # must return an instance of the worker that handles
15
15
  # message received on queue
16
16
  fail NotImplementedError
@@ -21,12 +21,12 @@ module Shoryuken
21
21
  fail NotImplementedError
22
22
  end
23
23
 
24
- def register_worker(queue, clazz)
24
+ def register_worker(_queue, _clazz)
25
25
  # must register the worker as a consumer of messages from queue
26
26
  fail NotImplementedError
27
27
  end
28
28
 
29
- def workers(queue)
29
+ def workers(_queue)
30
30
  # must return the list of workers registered for queue, or []
31
31
  fail NotImplementedError
32
32
  end
data/lib/shoryuken.rb CHANGED
@@ -1,8 +1,14 @@
1
1
  require 'yaml'
2
2
  require 'json'
3
3
  require 'aws-sdk-core'
4
+ begin
5
+ require 'aws-sdk-sqs' unless defined?(Aws::SQS)
6
+ rescue LoadError
7
+ fail "AWS SDK 3 requires aws-sdk-sqs to be installed separately. Please add gem 'aws-sdk-sqs' to your Gemfile"
8
+ end
4
9
  require 'time'
5
10
  require 'concurrent'
11
+ require 'forwardable'
6
12
 
7
13
  require 'shoryuken/version'
8
14
  require 'shoryuken/core_ext'
@@ -13,6 +19,8 @@ require 'shoryuken/queue'
13
19
  require 'shoryuken/message'
14
20
  require 'shoryuken/client'
15
21
  require 'shoryuken/worker'
22
+ require 'shoryuken/worker/default_executor'
23
+ require 'shoryuken/worker/inline_executor'
16
24
  require 'shoryuken/worker_registry'
17
25
  require 'shoryuken/default_worker_registry'
18
26
  require 'shoryuken/middleware/chain'
@@ -20,184 +28,57 @@ require 'shoryuken/middleware/server/auto_delete'
20
28
  Shoryuken::Middleware::Server.autoload :AutoExtendVisibility, 'shoryuken/middleware/server/auto_extend_visibility'
21
29
  require 'shoryuken/middleware/server/exponential_backoff_retry'
22
30
  require 'shoryuken/middleware/server/timing'
23
- require 'shoryuken/polling'
31
+ require 'shoryuken/polling/base'
32
+ require 'shoryuken/polling/weighted_round_robin'
33
+ require 'shoryuken/polling/strict_priority'
24
34
  require 'shoryuken/manager'
25
35
  require 'shoryuken/launcher'
26
36
  require 'shoryuken/processor'
37
+ require 'shoryuken/body_parser'
27
38
  require 'shoryuken/fetcher'
39
+ require 'shoryuken/options'
28
40
 
29
41
  module Shoryuken
30
- DEFAULTS = {
31
- concurrency: 25,
32
- queues: [],
33
- aws: {},
34
- delay: 0,
35
- timeout: 8,
36
- lifecycle_events: {
37
- startup: [],
38
- quiet: [],
39
- shutdown: []
40
- },
41
- polling_strategy: Polling::WeightedRoundRobin
42
- }.freeze
43
-
44
- @@queues = []
45
- @@worker_registry = DefaultWorkerRegistry.new
46
- @@active_job_queue_name_prefixing = false
47
- @@sqs_client = nil
48
- @@sqs_client_receive_message_opts = {}
49
- @@start_callback = nil
50
- @@stop_callback = nil
51
-
52
- class << self
53
- def queues
54
- @@queues
55
- end
56
-
57
- def add_queue(queue, priority = 1)
58
- priority.times { queues << queue }
59
- end
60
-
61
- def worker_registry
62
- @@worker_registry
63
- end
64
-
65
- def worker_registry=(worker_registry)
66
- @@worker_registry = worker_registry
67
- end
68
-
69
- def start_callback
70
- @@start_callback
71
- end
72
-
73
- def start_callback=(start_callback)
74
- @@start_callback = start_callback
75
- end
76
-
77
- def stop_callback
78
- @@stop_callback
79
- end
80
-
81
- def stop_callback=(stop_callback)
82
- @@stop_callback = stop_callback
83
- end
84
-
85
- def active_job_queue_name_prefixing
86
- @@active_job_queue_name_prefixing
87
- end
88
-
89
- def active_job_queue_name_prefixing=(active_job_queue_name_prefixing)
90
- @@active_job_queue_name_prefixing = active_job_queue_name_prefixing
91
- end
92
-
93
- def sqs_client
94
- @@sqs_client ||= Aws::SQS::Client.new
95
- end
96
-
97
- def sqs_client=(sqs_client)
98
- @@sqs_client = sqs_client
99
- end
100
-
101
- def sqs_client_receive_message_opts
102
- @@sqs_client_receive_message_opts
103
- end
104
-
105
- def sqs_client_receive_message_opts=(sqs_client_receive_message_opts)
106
- @@sqs_client_receive_message_opts = sqs_client_receive_message_opts
107
- end
108
-
109
- def options
110
- @@options ||= DEFAULTS.dup
111
- end
112
-
113
- def logger
114
- Shoryuken::Logging.logger
115
- end
116
-
117
- def register_worker(*args)
118
- @@worker_registry.register_worker(*args)
119
- end
120
-
121
- def configure_server
122
- yield self if server?
123
- end
124
-
125
- def server_middleware
126
- @@server_chain ||= default_server_middleware
127
- yield @@server_chain if block_given?
128
- @@server_chain
129
- end
130
-
131
- def configure_client
132
- yield self unless server?
133
- end
134
-
135
- def client_middleware
136
- @@client_chain ||= default_client_middleware
137
- yield @@client_chain if block_given?
138
- @@client_chain
139
- end
140
-
141
- def default_worker_options
142
- @@default_worker_options ||= {
143
- 'queue' => 'default',
144
- 'delete' => false,
145
- 'auto_delete' => false,
146
- 'auto_visibility_timeout' => false,
147
- 'retry_intervals' => nil,
148
- 'batch' => false
149
- }
150
- end
151
-
152
- def default_worker_options=(default_worker_options)
153
- @@default_worker_options = default_worker_options
154
- end
155
-
156
- def on_start(&block)
157
- @@start_callback = block
158
- end
159
-
160
- def on_stop(&block)
161
- @@stop_callback = block
162
- end
163
-
164
- # Register a block to run at a point in the Shoryuken lifecycle.
165
- # :startup, :quiet or :shutdown are valid events.
166
- #
167
- # Shoryuken.configure_server do |config|
168
- # config.on(:shutdown) do
169
- # puts "Goodbye cruel world!"
170
- # end
171
- # end
172
- def on(event, &block)
173
- fail ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
174
- fail ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
175
- options[:lifecycle_events][event] << block
176
- end
177
-
178
- private
179
-
180
- def default_server_middleware
181
- Middleware::Chain.new do |m|
182
- m.add Middleware::Server::Timing
183
- m.add Middleware::Server::ExponentialBackoffRetry
184
- m.add Middleware::Server::AutoDelete
185
- m.add Middleware::Server::AutoExtendVisibility
186
- if defined?(::ActiveRecord::Base)
187
- require 'shoryuken/middleware/server/active_record'
188
- m.add Middleware::Server::ActiveRecord
189
- end
190
- end
191
- end
192
-
193
- def default_client_middleware
194
- Middleware::Chain.new
195
- end
196
-
197
- def server?
198
- defined?(Shoryuken::CLI)
199
- end
200
- end
42
+ extend SingleForwardable
43
+
44
+ def_delegators(
45
+ :'Shoryuken::Options',
46
+ :active_job?,
47
+ :add_group,
48
+ :groups,
49
+ :add_queue,
50
+ :ungrouped_queues,
51
+ :worker_registry,
52
+ :worker_registry=,
53
+ :worker_executor,
54
+ :worker_executor=,
55
+ :launcher_executor,
56
+ :launcher_executor=,
57
+ :polling_strategy,
58
+ :start_callback,
59
+ :start_callback=,
60
+ :stop_callback,
61
+ :stop_callback=,
62
+ :active_job_queue_name_prefixing,
63
+ :active_job_queue_name_prefixing=,
64
+ :sqs_client,
65
+ :sqs_client=,
66
+ :sqs_client_receive_message_opts,
67
+ :sqs_client_receive_message_opts=,
68
+ :options,
69
+ :logger,
70
+ :register_worker,
71
+ :configure_server,
72
+ :server?,
73
+ :server_middleware,
74
+ :configure_client,
75
+ :client_middleware,
76
+ :default_worker_options,
77
+ :default_worker_options=,
78
+ :on_start,
79
+ :on_stop,
80
+ :on
81
+ )
201
82
  end
202
83
 
203
- require 'shoryuken/extensions/active_job_adapter' if defined?(::ActiveJob)
84
+ require 'shoryuken/extensions/active_job_adapter' if Shoryuken.active_job?
data/shoryuken.gemspec CHANGED
@@ -1,5 +1,5 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+
2
+ lib = File.expand_path('lib', __dir__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'shoryuken/version'
5
5
 
@@ -13,17 +13,17 @@ Gem::Specification.new do |spec|
13
13
  spec.license = 'LGPL-3.0'
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = %w(shoryuken)
16
+ spec.executables = %w[shoryuken]
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
20
  spec.add_development_dependency 'bundler', '~> 1.6'
21
+ spec.add_development_dependency 'dotenv'
22
+ spec.add_development_dependency 'pry-byebug'
21
23
  spec.add_development_dependency 'rake'
22
24
  spec.add_development_dependency 'rspec'
23
- spec.add_development_dependency 'pry-byebug'
24
- spec.add_development_dependency 'dotenv'
25
25
 
26
- spec.add_dependency 'aws-sdk-core', '~> 2'
26
+ spec.add_dependency 'aws-sdk-core', '>= 2'
27
27
  spec.add_dependency 'concurrent-ruby'
28
28
  spec.add_dependency 'thor'
29
29
  end
@@ -4,27 +4,33 @@ require 'shoryuken/launcher'
4
4
  require 'securerandom'
5
5
 
6
6
  RSpec.describe Shoryuken::Launcher do
7
- describe 'Consuming messages', slow: :true do
7
+ describe 'Consuming messages', slow: true do
8
8
  before do
9
+ Aws.config[:stub_responses] = false
10
+ Aws.config[:region] = 'us-east-1'
11
+
9
12
  StandardWorker.received_messages = 0
10
13
 
11
- queue = "test_shoryuken#{StandardWorker}_#{SecureRandom.uuid}"
14
+ queue = "shoryuken-travis-#{StandardWorker}-#{SecureRandom.uuid}"
12
15
 
13
- Shoryuken::Client.sqs.create_queue queue_name: queue
16
+ Shoryuken::Client.sqs.create_queue(queue_name: queue)
14
17
 
15
- Shoryuken.queues << queue
18
+ Shoryuken.add_group('default', 1)
19
+ Shoryuken.add_queue(queue, 1, 'default')
16
20
 
17
21
  StandardWorker.get_shoryuken_options['queue'] = queue
18
22
 
19
- Shoryuken.register_worker queue, StandardWorker
23
+ Shoryuken.register_worker(queue, StandardWorker)
20
24
  end
21
25
 
22
26
  after do
27
+ Aws.config[:stub_responses] = true
28
+
23
29
  queue_url = Shoryuken::Client.sqs.get_queue_url(
24
30
  queue_name: StandardWorker.get_shoryuken_options['queue']
25
31
  ).queue_url
26
32
 
27
- Shoryuken::Client.sqs.delete_queue queue_url: queue_url
33
+ Shoryuken::Client.sqs.delete_queue(queue_url: queue_url)
28
34
  end
29
35
 
30
36
  it 'consumes as a command worker' do
@@ -61,7 +67,7 @@ RSpec.describe Shoryuken::Launcher do
61
67
  end
62
68
 
63
69
  def poll_queues_until
64
- subject.run
70
+ subject.start
65
71
 
66
72
  Timeout::timeout(10) do
67
73
  begin
@@ -79,7 +85,7 @@ RSpec.describe Shoryuken::Launcher do
79
85
 
80
86
  shoryuken_options auto_delete: true
81
87
 
82
- def perform(sqs_msg, body)
88
+ def perform(sqs_msg, _body)
83
89
  @@received_messages += Array(sqs_msg).size
84
90
  end
85
91
 
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+ require 'shoryuken/body_parser'
3
+
4
+ RSpec.describe Shoryuken::BodyParser do
5
+ let(:sqs_msg) { double }
6
+
7
+ describe '#parser' do
8
+ it 'parses the body into JSON' do
9
+ TestWorker.get_shoryuken_options['body_parser'] = :json
10
+
11
+ body = { 'test' => 'hi' }
12
+
13
+ allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
14
+
15
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq(body)
16
+ end
17
+
18
+ it 'parses the body calling the proc' do
19
+ TestWorker.get_shoryuken_options['body_parser'] = proc { |sqs_msg| "*#{sqs_msg.body}*" }
20
+
21
+ allow(sqs_msg).to receive(:body).and_return('test')
22
+
23
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq('*test*')
24
+ end
25
+
26
+ it 'parses the body as text' do
27
+ TestWorker.get_shoryuken_options['body_parser'] = :text
28
+
29
+ body = 'test'
30
+
31
+ allow(sqs_msg).to receive(:body).and_return(body)
32
+
33
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq('test')
34
+ end
35
+
36
+ it 'parses calling `.load`' do
37
+ TestWorker.get_shoryuken_options['body_parser'] = Class.new do
38
+ def self.load(*args)
39
+ JSON.load(*args)
40
+ end
41
+ end
42
+
43
+ body = { 'test' => 'hi' }
44
+
45
+ allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
46
+
47
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq(body)
48
+ end
49
+
50
+ it 'parses calling `.parse`' do
51
+ TestWorker.get_shoryuken_options['body_parser'] = Class.new do
52
+ def self.parse(*args)
53
+ JSON.parse(*args)
54
+ end
55
+ end
56
+
57
+ body = { 'test' => 'hi' }
58
+
59
+ allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
60
+
61
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq(body)
62
+ end
63
+
64
+ context 'when parse errors' do
65
+ before do
66
+ TestWorker.get_shoryuken_options['body_parser'] = :json
67
+
68
+ allow(sqs_msg).to receive(:body).and_return('invalid JSON')
69
+ end
70
+
71
+ specify do
72
+ expect { described_class.parse(TestWorker, sqs_msg) }
73
+ .to raise_error(JSON::ParserError, /unexpected token at 'invalid JSON'/)
74
+ end
75
+ end
76
+
77
+ context 'when `object_type: nil`' do
78
+ it 'parses the body as text' do
79
+ TestWorker.get_shoryuken_options['body_parser'] = nil
80
+
81
+ body = 'test'
82
+
83
+ allow(sqs_msg).to receive(:body).and_return(body)
84
+
85
+ expect(described_class.parse(TestWorker, sqs_msg)).to eq(body)
86
+ end
87
+ end
88
+ end
89
+ end