shoryuken 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -36
- data/Rakefile +9 -5
- data/examples/all.rb +3 -3
- data/examples/default_worker.rb +9 -0
- data/examples/high_priority_worker.rb +9 -0
- data/examples/low_priority_worker.rb +11 -0
- data/lib/shoryuken.rb +4 -4
- data/lib/shoryuken/cli.rb +33 -13
- data/lib/shoryuken/client.rb +4 -0
- data/lib/shoryuken/launcher.rb +1 -1
- data/lib/shoryuken/middleware/chain.rb +18 -0
- data/lib/shoryuken/middleware/server/auto_delete.rb +18 -0
- data/lib/shoryuken/middleware/server/{logging.rb → timing.rb} +5 -5
- data/lib/shoryuken/processor.rb +36 -9
- data/lib/shoryuken/util.rb +1 -0
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken/worker.rb +4 -0
- data/shoryuken.gemspec +0 -1
- data/spec/integration/launcher_spec.rb +18 -10
- data/spec/shoryuken/client_spec.rb +14 -0
- data/spec/shoryuken/fetcher_spec.rb +3 -11
- data/spec/shoryuken/middleware/chain_spec.rb +24 -3
- data/spec/shoryuken/middleware/server/auto_delete_spec.rb +50 -0
- data/spec/shoryuken/middleware/server/timing_spec.rb +37 -0
- data/spec/shoryuken/processor_spec.rb +79 -21
- data/spec/shoryuken/worker_spec.rb +24 -10
- data/spec/spec_helper.rb +12 -1
- metadata +11 -23
- data/examples/shoryuken_worker.rb +0 -11
- data/examples/sidekiq_worker.rb +0 -11
- data/examples/uppercut_worker.rb +0 -11
- data/lib/shoryuken/middleware/server/delete.rb +0 -17
- data/spec/shoryuken/middleware/server/delete_spec.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3afa1e42164a3fc885caf45222d317ac77692c3b
|
4
|
+
data.tar.gz: 9abfa8e2c9ed9b4540bbb422fba35a3f00591364
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35934726404b3d5454b1bc97875d3ba8934d2ef4efa4a354dbff97af95959c647757259ffc6fefc53a8ffaab5c1cfeffad73d79aff50a3575f5e65d39cbbb553
|
7
|
+
data.tar.gz: 6cafc6fbfd06fff62541acc41169877440454eba4afb1688728bbd69330ed53fa9a62d1c28b2b9a057de853952cff26d537d013747a8cc5b6c47a8b637f3c1f2
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ Shoryuken _sho-ryu-ken_ is a super efficient [AWS SQS](https://aws.amazon.com/sq
|
|
10
10
|
|
11
11
|
### Load balancing
|
12
12
|
|
13
|
-
Yeah, Shoryuken load balances the messages consumption
|
13
|
+
Yeah, Shoryuken load balances the messages consumption!
|
14
14
|
|
15
15
|
Given this configuration:
|
16
16
|
|
@@ -18,19 +18,21 @@ Given this configuration:
|
|
18
18
|
concurrency: 25,
|
19
19
|
delay: 25,
|
20
20
|
queues:
|
21
|
-
- [
|
22
|
-
- [
|
23
|
-
- [
|
21
|
+
- [high_priority, 6]
|
22
|
+
- [default, 2]
|
23
|
+
- [low_priority, 1]
|
24
24
|
```
|
25
25
|
|
26
|
-
And supposing all the queues are full of messages, the configuration above will make Shoryuken to process
|
27
|
-
splitting the work among the 25 available processors.
|
26
|
+
And supposing all the queues are full of messages, the configuration above will make Shoryuken to process `high_priority` 3 times more than `default` and 6 times more than `low_priority`,
|
27
|
+
splitting the work among the `concurrency: 25` available processors.
|
28
28
|
|
29
|
-
If
|
29
|
+
If `high_priority` gets empty, Shoryuken will keep using the 25 processors, but only to process `default` (2 times more than `low_priority`) and `low_priority`.
|
30
30
|
|
31
|
-
If
|
31
|
+
If `high_priority` receives a new message, Shoryuken will smoothly increase back the `high_priority` weight one by one until it reaches the weight of 6 again, which is the maximum configured for `high_priority`.
|
32
32
|
|
33
|
-
If all queues get empty, all processors will be changed to the waiting state and the queues will be checked every `delay: 25`. If any queue
|
33
|
+
If all queues get empty, all processors will be changed to the waiting state and the queues will be checked every `delay: 25`. If any queue receives a new message, Shoryuken will start processing again.
|
34
|
+
|
35
|
+
*You can set `delay: 0` to continuously check the queues without pausing even if they are empty.*
|
34
36
|
|
35
37
|
### Fetch in batches
|
36
38
|
|
@@ -42,6 +44,10 @@ Add this line to your application's Gemfile:
|
|
42
44
|
|
43
45
|
gem 'shoryuken'
|
44
46
|
|
47
|
+
**Require Shoryuken from GitHub to get the latest updates:**
|
48
|
+
|
49
|
+
gem 'shoryuken', github: 'phstc/shoryuken', branch: 'master'
|
50
|
+
|
45
51
|
And then execute:
|
46
52
|
|
47
53
|
$ bundle
|
@@ -55,24 +61,51 @@ Or install it yourself as:
|
|
55
61
|
### Worker class
|
56
62
|
|
57
63
|
```ruby
|
58
|
-
class
|
64
|
+
class MyWorker
|
59
65
|
include Shoryuken::Worker
|
60
66
|
|
61
|
-
shoryuken_options queue: '
|
62
|
-
# shoryuken_options queue: ->{ "#{ENV['environment']
|
67
|
+
shoryuken_options queue: 'default', delete: true
|
68
|
+
# shoryuken_options queue: ->{ "#{ENV['environment']_default" }
|
69
|
+
|
70
|
+
# shoryuken_options body_parser: :json
|
71
|
+
# shoryuken_options body_parser: ->(sqs_msg){ REXML::Document.new(sqs_msg.body) }
|
72
|
+
# shoryuken_options body_parser: JSON
|
63
73
|
|
64
|
-
def perform(sqs_msg)
|
65
|
-
puts
|
74
|
+
def perform(sqs_msg, body)
|
75
|
+
puts body
|
66
76
|
end
|
67
77
|
end
|
68
78
|
```
|
69
79
|
|
80
|
+
[Check the Worker options documention](https://github.com/phstc/shoryuken/wiki/Worker-options).
|
81
|
+
|
70
82
|
### Sending a message
|
71
83
|
|
72
84
|
```ruby
|
73
|
-
|
85
|
+
MyWorker.perform_async('Pablo')
|
86
|
+
# or
|
87
|
+
Shoryuken::Client.queues('default').send_message('Pablo')
|
88
|
+
|
89
|
+
# delaying a message
|
90
|
+
MyWorker.perform_async('Pablo', delay_seconds: 60)
|
91
|
+
# or
|
92
|
+
Shoryuken::Client.queues('default').send_message('Pablo', delay_seconds: 60)
|
93
|
+
```
|
94
|
+
|
95
|
+
### Midleware
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
class MyMiddleware
|
99
|
+
def call(worker_instance, queue, sqs_msg, body)
|
100
|
+
puts 'Before work'
|
101
|
+
yield
|
102
|
+
puts 'After work'
|
103
|
+
end
|
104
|
+
end
|
74
105
|
```
|
75
106
|
|
107
|
+
[Check the Middleware documentation](https://github.com/phstc/shoryuken/wiki/Middleware).
|
108
|
+
|
76
109
|
### Configuration
|
77
110
|
|
78
111
|
Sample configuration file `shoryuken.yml`.
|
@@ -90,9 +123,9 @@ aws:
|
|
90
123
|
concurrency: 25, # The number of allocated threads to process messages. Default 25
|
91
124
|
delay: 25, # The delay in seconds to pause a queue when it's empty. Default 0
|
92
125
|
queues:
|
93
|
-
- [
|
94
|
-
- [
|
95
|
-
- [
|
126
|
+
- [high_priority, 6]
|
127
|
+
- [default, 2]
|
128
|
+
- [low_priority, 1]
|
96
129
|
```
|
97
130
|
|
98
131
|
### Start Shoryuken
|
@@ -120,24 +153,6 @@ shoryuken [options]
|
|
120
153
|
...
|
121
154
|
```
|
122
155
|
|
123
|
-
### Middleware
|
124
|
-
|
125
|
-
```ruby
|
126
|
-
class MyServerHook
|
127
|
-
def call(worker_instance, queue, sqs_msg)
|
128
|
-
puts 'Before work'
|
129
|
-
yield
|
130
|
-
puts 'After work'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
Shoryuken.configure_server do |config|
|
135
|
-
config.server_middleware do |chain|
|
136
|
-
chain.add MyServerHook
|
137
|
-
# chain.remove MyServerHook
|
138
|
-
end
|
139
|
-
end
|
140
|
-
```
|
141
156
|
|
142
157
|
## More Information
|
143
158
|
|
data/Rakefile
CHANGED
@@ -22,7 +22,7 @@ task :console do
|
|
22
22
|
Pry.start
|
23
23
|
end
|
24
24
|
|
25
|
-
desc 'Push test messages to
|
25
|
+
desc 'Push test messages to high_priority, default and low_priority'
|
26
26
|
task :push_test, :size do |t, args|
|
27
27
|
require 'yaml'
|
28
28
|
require 'shoryuken'
|
@@ -31,13 +31,17 @@ task :push_test, :size do |t, args|
|
|
31
31
|
|
32
32
|
AWS.config(config['aws'])
|
33
33
|
|
34
|
+
Shoryuken::Client.sqs.queues.create('default')
|
35
|
+
Shoryuken::Client.sqs.queues.create('high_priority')
|
36
|
+
Shoryuken::Client.sqs.queues.create('low_priority')
|
37
|
+
|
34
38
|
(args[:size] || 1).to_i.times.map do |i|
|
35
39
|
Thread.new do
|
36
|
-
|
37
|
-
Shoryuken::Client.queues('uppercut').send_message("uppercut #{i}")
|
38
|
-
Shoryuken::Client.queues('sidekiq').send_message("sidekiq #{i}")
|
40
|
+
puts "Pushing test ##{i}"
|
39
41
|
|
40
|
-
|
42
|
+
Shoryuken::Client.queues('high_priority').send_message("test #{i}")
|
43
|
+
Shoryuken::Client.queues('default').send_message("test #{i}")
|
44
|
+
Shoryuken::Client.queues('low_priority').send_message("test #{i}")
|
41
45
|
end
|
42
46
|
end.each &:join
|
43
47
|
end
|
data/examples/all.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
class LowPriorityWorker
|
2
|
+
include Shoryuken::Worker
|
3
|
+
|
4
|
+
shoryuken_options queue: 'low_priority', delete: true, batch: true
|
5
|
+
|
6
|
+
def perform(sqs_msgs, bodies)
|
7
|
+
bodies.each_with_index do |body, index|
|
8
|
+
puts "LowPriorityWorker (#{index}): '#{body}'"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/shoryuken.rb
CHANGED
@@ -9,8 +9,8 @@ require 'shoryuken/client'
|
|
9
9
|
require 'shoryuken/worker'
|
10
10
|
require 'shoryuken/logging'
|
11
11
|
require 'shoryuken/middleware/chain'
|
12
|
-
require 'shoryuken/middleware/server/
|
13
|
-
require 'shoryuken/middleware/server/
|
12
|
+
require 'shoryuken/middleware/server/auto_delete'
|
13
|
+
require 'shoryuken/middleware/server/timing'
|
14
14
|
|
15
15
|
module Shoryuken
|
16
16
|
DEFAULTS = {
|
@@ -64,8 +64,8 @@ module Shoryuken
|
|
64
64
|
|
65
65
|
def self.default_server_middleware
|
66
66
|
Middleware::Chain.new do |m|
|
67
|
-
m.add Middleware::Server::
|
68
|
-
m.add Middleware::Server::
|
67
|
+
m.add Middleware::Server::Timing
|
68
|
+
m.add Middleware::Server::AutoDelete
|
69
69
|
# TODO m.add Middleware::Server::RetryJobs
|
70
70
|
end
|
71
71
|
end
|
data/lib/shoryuken/cli.rb
CHANGED
@@ -16,7 +16,7 @@ module Shoryuken
|
|
16
16
|
def run(args)
|
17
17
|
self_read, self_write = IO.pipe
|
18
18
|
|
19
|
-
%w
|
19
|
+
%w[INT TERM USR1 USR2 TTIN].each do |sig|
|
20
20
|
trap sig do
|
21
21
|
self_write.puts(sig)
|
22
22
|
end
|
@@ -24,11 +24,12 @@ module Shoryuken
|
|
24
24
|
|
25
25
|
setup_options(args)
|
26
26
|
initialize_logger
|
27
|
+
require_workers
|
27
28
|
validate!
|
29
|
+
patch_deprecated_workers!
|
28
30
|
daemonize
|
29
31
|
write_pid
|
30
32
|
load_celluloid
|
31
|
-
require_workers
|
32
33
|
|
33
34
|
require 'shoryuken/launcher'
|
34
35
|
@launcher = Shoryuken::Launcher.new
|
@@ -144,7 +145,7 @@ module Shoryuken
|
|
144
145
|
|
145
146
|
@parser.banner = 'shoryuken [options]'
|
146
147
|
@parser.on_tail '-h', '--help', 'Show help' do
|
147
|
-
|
148
|
+
logger.info @parser
|
148
149
|
exit 1
|
149
150
|
end
|
150
151
|
@parser.parse!(argv)
|
@@ -152,22 +153,22 @@ module Shoryuken
|
|
152
153
|
end
|
153
154
|
|
154
155
|
def handle_signal(sig)
|
155
|
-
|
156
|
+
logger.info "Got #{sig} signal"
|
156
157
|
|
157
158
|
case sig
|
158
159
|
when 'USR1'
|
159
|
-
|
160
|
+
logger.info "Received USR1, will soft shutdown down"
|
160
161
|
|
161
162
|
launcher.stop
|
162
163
|
|
163
164
|
exit 0
|
164
165
|
when 'TTIN'
|
165
166
|
Thread.list.each do |thread|
|
166
|
-
|
167
|
+
logger.info "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
167
168
|
if thread.backtrace
|
168
|
-
|
169
|
+
logger.info thread.backtrace.join("\n")
|
169
170
|
else
|
170
|
-
|
171
|
+
logger.info "<no backtrace available>"
|
171
172
|
end
|
172
173
|
end
|
173
174
|
|
@@ -175,9 +176,9 @@ module Shoryuken
|
|
175
176
|
busy = launcher.manager.instance_variable_get(:@busy).size
|
176
177
|
queues = launcher.manager.instance_variable_get(:@queues)
|
177
178
|
|
178
|
-
|
179
|
+
logger.info "Ready: #{ready}, Busy: #{busy}, Active Queues: #{unparse_queues(queues)}"
|
179
180
|
else
|
180
|
-
|
181
|
+
logger.info "Received #{sig}, will shutdown down"
|
181
182
|
|
182
183
|
raise Interrupt
|
183
184
|
end
|
@@ -210,13 +211,18 @@ module Shoryuken
|
|
210
211
|
end
|
211
212
|
|
212
213
|
def validate!
|
214
|
+
raise ArgumentError, 'No queues supplied' if Shoryuken.queues.empty?
|
215
|
+
|
216
|
+
if queue_without_worker = Shoryuken.queues.find { |queue| Shoryuken.workers[queue].nil? }
|
217
|
+
raise ArgumentError, "No worker supplied for #{queue_without_worker}"
|
218
|
+
end
|
219
|
+
|
213
220
|
if Shoryuken.options[:aws][:access_key_id].nil? && Shoryuken.options[:aws][:secret_access_key].nil?
|
214
221
|
if ENV['AWS_ACCESS_KEY_ID'].nil? && ENV['AWS_SECRET_ACCESS_KEY'].nil?
|
215
222
|
raise ArgumentError, 'No AWS credentials supplied'
|
216
223
|
end
|
217
224
|
end
|
218
225
|
|
219
|
-
|
220
226
|
initialize_aws
|
221
227
|
|
222
228
|
Shoryuken.queues.uniq.each do |queue|
|
@@ -229,8 +235,6 @@ module Shoryuken
|
|
229
235
|
raise
|
230
236
|
end
|
231
237
|
end
|
232
|
-
|
233
|
-
raise ArgumentError, 'No queues supplied' if Shoryuken.queues.empty?
|
234
238
|
end
|
235
239
|
|
236
240
|
def initialize_aws
|
@@ -250,5 +254,21 @@ module Shoryuken
|
|
250
254
|
def parse_queue(queue, weight = nil)
|
251
255
|
[weight.to_i, 1].max.times { Shoryuken.queues << queue }
|
252
256
|
end
|
257
|
+
|
258
|
+
def patch_deprecated_workers!
|
259
|
+
Shoryuken.workers.each do |queue, worker_class|
|
260
|
+
if worker_class.instance_method(:perform).arity == 1
|
261
|
+
logger.warn "[DEPRECATION] #{worker_class.name}#perform(sqs_msg) is deprecated. Please use #{worker_class.name}#perform(sqs_msg, body)"
|
262
|
+
|
263
|
+
worker_class.class_eval do
|
264
|
+
alias_method :deprecated_perform, :perform
|
265
|
+
|
266
|
+
def perform(sqs_msg, body = nil)
|
267
|
+
deprecated_perform(sqs_msg)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
253
273
|
end
|
254
274
|
end
|
data/lib/shoryuken/client.rb
CHANGED
data/lib/shoryuken/launcher.rb
CHANGED
@@ -34,7 +34,7 @@ module Shoryuken
|
|
34
34
|
|
35
35
|
def actor_died(actor, reason)
|
36
36
|
return if @done
|
37
|
-
|
37
|
+
logger.warn 'Shoryuken died due to the following error, cannot recover, process exiting'
|
38
38
|
exit 1
|
39
39
|
end
|
40
40
|
end
|
@@ -101,11 +101,29 @@ module Shoryuken
|
|
101
101
|
def initialize(klass, *args)
|
102
102
|
@klass = klass
|
103
103
|
@args = args
|
104
|
+
|
105
|
+
patch_deprecated_middleware!(klass)
|
104
106
|
end
|
105
107
|
|
106
108
|
def make_new
|
107
109
|
@klass.new(*@args)
|
108
110
|
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def patch_deprecated_middleware!(klass)
|
115
|
+
if klass.instance_method(:call).arity == 3
|
116
|
+
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)"
|
117
|
+
|
118
|
+
klass.class_eval do
|
119
|
+
alias_method :deprecated_call, :call
|
120
|
+
|
121
|
+
def call(worker_instance, queue, sqs_msg, body = nil, &block)
|
122
|
+
deprecated_call(worker_instance, queue, sqs_msg, &block)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
109
127
|
end
|
110
128
|
end
|
111
129
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Shoryuken
|
2
|
+
module Middleware
|
3
|
+
module Server
|
4
|
+
class AutoDelete
|
5
|
+
|
6
|
+
def call(worker, queue, sqs_msg, body)
|
7
|
+
yield
|
8
|
+
|
9
|
+
# I'm still deciding, but `auto_delete` will be probably deprecated soon
|
10
|
+
delete = worker.class.get_shoryuken_options['delete'] || worker.class.get_shoryuken_options['auto_delete']
|
11
|
+
|
12
|
+
Shoryuken::Client.queues(queue).batch_delete(*Array(sqs_msg)) if delete
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Shoryuken
|
2
2
|
module Middleware
|
3
3
|
module Server
|
4
|
-
class
|
4
|
+
class Timing
|
5
5
|
include Util
|
6
6
|
|
7
|
-
def call(worker, queue, sqs_msg)
|
7
|
+
def call(worker, queue, sqs_msg, body)
|
8
8
|
Shoryuken::Logging.with_context("#{worker.class.to_s}/#{queue}/#{sqs_msg.id}") do
|
9
9
|
begin
|
10
10
|
started_at = Time.now
|
11
11
|
|
12
|
-
logger.info
|
12
|
+
logger.info "started at #{started_at}"
|
13
13
|
|
14
14
|
yield
|
15
15
|
|
@@ -19,9 +19,9 @@ module Shoryuken
|
|
19
19
|
logger.warn "exceeded the queue visibility timeout by #{total_time - (timeout * 1000)} ms"
|
20
20
|
end
|
21
21
|
|
22
|
-
logger.info
|
22
|
+
logger.info "completed in: #{total_time} ms"
|
23
23
|
rescue => e
|
24
|
-
logger.info
|
24
|
+
logger.info "failed in: #{elapsed(started_at)} ms"
|
25
25
|
raise e
|
26
26
|
end
|
27
27
|
end
|
data/lib/shoryuken/processor.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'json'
|
2
2
|
|
3
3
|
module Shoryuken
|
4
4
|
class Processor
|
@@ -10,19 +10,46 @@ module Shoryuken
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def process(queue, sqs_msg)
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
worker_class = Shoryuken.workers[queue]
|
14
|
+
defer do
|
15
|
+
body = get_body(worker_class, sqs_msg)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
worker = worker_class.new
|
18
|
+
|
19
|
+
Shoryuken.server_middleware.invoke(worker, queue, sqs_msg, body) do
|
20
|
+
worker.perform(sqs_msg, body)
|
20
21
|
end
|
21
|
-
else
|
22
|
-
logger.error "Worker not found for queue '#{queue}'"
|
23
22
|
end
|
24
23
|
|
25
24
|
@manager.async.processor_done(queue, current_actor)
|
26
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def get_body(worker_class, sqs_msg)
|
30
|
+
if sqs_msg.is_a? Array
|
31
|
+
sqs_msg.map { |m| parse_body(worker_class, m) }
|
32
|
+
else
|
33
|
+
parse_body(worker_class, sqs_msg)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_body(worker_class, sqs_msg)
|
38
|
+
body_parser = worker_class.get_shoryuken_options['body_parser']
|
39
|
+
|
40
|
+
case body_parser
|
41
|
+
when :json
|
42
|
+
JSON.parse(sqs_msg.body)
|
43
|
+
when Proc
|
44
|
+
body_parser.call(sqs_msg)
|
45
|
+
when :text, nil
|
46
|
+
sqs_msg.body
|
47
|
+
else
|
48
|
+
body_parser.parse(sqs_msg.body) if body_parser.respond_to?(:parse) # i.e. JSON.parse(...)
|
49
|
+
end
|
50
|
+
rescue => e
|
51
|
+
logger.error "Error parsing the message body: #{e.message}\nbody_parser: #{body_parser}\nsqs_msg.body: #{sqs_msg.body}"
|
52
|
+
nil
|
53
|
+
end
|
27
54
|
end
|
28
55
|
end
|
data/lib/shoryuken/util.rb
CHANGED
data/lib/shoryuken/version.rb
CHANGED
data/lib/shoryuken/worker.rb
CHANGED
@@ -5,6 +5,10 @@ module Shoryuken
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
+
def perform_async(body, options = {})
|
9
|
+
Shoryuken::Client.send_message(get_shoryuken_options['queue'], body, options)
|
10
|
+
end
|
11
|
+
|
8
12
|
def shoryuken_options(opts = {})
|
9
13
|
@shoryuken_options = get_shoryuken_options.merge(stringify_keys(Hash(opts)))
|
10
14
|
queue = @shoryuken_options['queue']
|
data/shoryuken.gemspec
CHANGED
@@ -11,20 +11,28 @@ describe Shoryuken::Launcher do
|
|
11
11
|
|
12
12
|
subject.run
|
13
13
|
|
14
|
-
|
14
|
+
ShoryukenWorker.received_messages = 0
|
15
15
|
end
|
16
16
|
|
17
|
-
after
|
18
|
-
subject.stop
|
19
|
-
end
|
17
|
+
after { subject.stop }
|
20
18
|
|
21
19
|
class ShoryukenWorker
|
22
20
|
include Shoryuken::Worker
|
23
21
|
|
22
|
+
@@received_messages = 0
|
23
|
+
|
24
24
|
shoryuken_options queue: 'shoryuken', delete: true
|
25
25
|
|
26
|
-
def perform(sqs_msg)
|
27
|
-
|
26
|
+
def perform(sqs_msg, body)
|
27
|
+
@@received_messages = Array(sqs_msg).size
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.received_messages
|
31
|
+
@@received_messages
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.received_messages=(received_messages)
|
35
|
+
@@received_messages = received_messages
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
@@ -34,11 +42,11 @@ describe Shoryuken::Launcher do
|
|
34
42
|
Shoryuken::Client.queues('shoryuken').send_message('Yo')
|
35
43
|
|
36
44
|
10.times do
|
37
|
-
break if
|
45
|
+
break if ShoryukenWorker.received_messages > 0
|
38
46
|
sleep 0.2
|
39
47
|
end
|
40
48
|
|
41
|
-
expect(
|
49
|
+
expect(ShoryukenWorker.received_messages).to eq 1
|
42
50
|
end
|
43
51
|
|
44
52
|
it 'consumes a batch' do
|
@@ -47,12 +55,12 @@ describe Shoryuken::Launcher do
|
|
47
55
|
Shoryuken::Client.queues('shoryuken').batch_send *(['Yo'] * 10)
|
48
56
|
|
49
57
|
10.times do
|
50
|
-
break if
|
58
|
+
break if ShoryukenWorker.received_messages > 0
|
51
59
|
sleep 0.2
|
52
60
|
end
|
53
61
|
|
54
62
|
# the fetch result is uncertain, should be greater than 1, but hard to tell the exact size
|
55
|
-
expect(
|
63
|
+
expect(ShoryukenWorker.received_messages).to be > 1
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -21,6 +21,20 @@ describe Shoryuken::Client do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
describe '.send_message' do
|
25
|
+
it 'enqueues a message' do
|
26
|
+
expect(sqs_queue).to receive(:send_message).with('test', {})
|
27
|
+
|
28
|
+
described_class.send_message(queue, 'test')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'enqueues a message with options' do
|
32
|
+
expect(sqs_queue).to receive(:send_message).with('test2', delay_seconds: 60)
|
33
|
+
|
34
|
+
described_class.send_message(queue, 'test2', delay_seconds: 60)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
24
38
|
describe '.visibility_timeout' do
|
25
39
|
it 'memoizes visibility_timeout' do
|
26
40
|
expect(sqs_queue).to receive(:visibility_timeout).once.and_return(30)
|
@@ -5,8 +5,8 @@ require 'shoryuken/fetcher'
|
|
5
5
|
describe Shoryuken::Fetcher do
|
6
6
|
let(:manager) { double Shoryuken::Manager }
|
7
7
|
let(:sqs_queue) { double 'sqs_queue' }
|
8
|
-
let(:queue) { '
|
9
|
-
let(:sqs_msg) { double
|
8
|
+
let(:queue) { 'default' }
|
9
|
+
let(:sqs_msg) { double AWS::SQS::ReceivedMessage, id: 'fc754df7-9cc2-4c41-96ca-5996a44b771e', body: 'test' }
|
10
10
|
|
11
11
|
subject { described_class.new(manager) }
|
12
12
|
|
@@ -16,14 +16,6 @@ describe Shoryuken::Fetcher do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
|
19
|
-
class Shoryuken2Worker
|
20
|
-
include Shoryuken::Worker
|
21
|
-
|
22
|
-
shoryuken_options queue: 'shoryuken2'
|
23
|
-
|
24
|
-
def perform(sqs_msg); end
|
25
|
-
end
|
26
|
-
|
27
19
|
describe '#fetch' do
|
28
20
|
it 'calls pause when no message' do
|
29
21
|
allow(sqs_queue).to receive(:receive_message).with(limit: 1).and_return([])
|
@@ -45,7 +37,7 @@ describe Shoryuken::Fetcher do
|
|
45
37
|
end
|
46
38
|
|
47
39
|
it 'assigns messages in batch' do
|
48
|
-
|
40
|
+
TestWorker.get_shoryuken_options['batch'] = true
|
49
41
|
|
50
42
|
allow(sqs_queue).to receive(:receive_message).with(limit: described_class::FETCH_LIMIT).and_return(sqs_msg)
|
51
43
|
|
@@ -20,7 +20,7 @@ describe Shoryuken::Middleware::Chain do
|
|
20
20
|
expect(CustomMiddleware).to eq subject.entries.last.klass
|
21
21
|
end
|
22
22
|
|
23
|
-
it '
|
23
|
+
it 'invokes a middleware' do
|
24
24
|
recorder = []
|
25
25
|
subject.add CustomMiddleware, 'Pablo', recorder
|
26
26
|
|
@@ -31,8 +31,7 @@ describe Shoryuken::Middleware::Chain do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class NonYieldingMiddleware
|
34
|
-
def call(*args)
|
35
|
-
end
|
34
|
+
def call(*args); end
|
36
35
|
end
|
37
36
|
|
38
37
|
it 'allows middleware to abruptly stop processing rest of chain' do
|
@@ -45,4 +44,26 @@ describe Shoryuken::Middleware::Chain do
|
|
45
44
|
expect(final_action).to eq nil
|
46
45
|
expect(recorder).to eq []
|
47
46
|
end
|
47
|
+
|
48
|
+
class DeprecatedMiddleware
|
49
|
+
def call(worker_instance, queue, sqs_msg)
|
50
|
+
@@success = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.success?
|
54
|
+
!!@@success
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'patches deprecated middleware' do
|
59
|
+
subject.clear
|
60
|
+
|
61
|
+
expect(Shoryuken.logger).to receive(:warn).with("[DEPRECATION] DeprecatedMiddleware#call(worker_instance, queue, sqs_msg) is deprecated. Please use DeprecatedMiddleware#call(worker_instance, queue, sqs_msg, body)")
|
62
|
+
|
63
|
+
subject.add DeprecatedMiddleware
|
64
|
+
|
65
|
+
subject.invoke TestWorker, 'test', double('SQS msg', body: 'test'), 'test'
|
66
|
+
|
67
|
+
expect(DeprecatedMiddleware.success?).to eq true
|
68
|
+
end
|
48
69
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoryuken::Middleware::Server::AutoDelete do
|
4
|
+
let(:sqs_msg) { double AWS::SQS::ReceivedMessage, id: 'fc754df7-9cc2-4c41-96ca-5996a44b771e', body: 'test' }
|
5
|
+
let(:queue) { 'default' }
|
6
|
+
let(:sqs_queue) { double AWS::SQS::Queue }
|
7
|
+
|
8
|
+
before do
|
9
|
+
allow(Shoryuken::Client).to receive(:queues).with(queue).and_return(sqs_queue)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'deletes a message' do
|
13
|
+
TestWorker.get_shoryuken_options['delete'] = true
|
14
|
+
|
15
|
+
expect(sqs_queue).to receive(:batch_delete).with(sqs_msg)
|
16
|
+
|
17
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) {}
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'deletes a batch' do
|
21
|
+
TestWorker.get_shoryuken_options['delete'] = true
|
22
|
+
|
23
|
+
sqs_msg2 = double 'SQS msg', body: 'test'
|
24
|
+
sqs_msg3 = double 'SQS msg', body: 'test'
|
25
|
+
|
26
|
+
sqs_msgs = [sqs_msg, sqs_msg2, sqs_msg3]
|
27
|
+
|
28
|
+
expect(sqs_queue).to receive(:batch_delete).with(*sqs_msgs)
|
29
|
+
|
30
|
+
subject.call(TestWorker.new, queue, sqs_msgs, [sqs_msg.body, sqs_msg2.body, sqs_msg3.body]) {}
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'does not delete a message' do
|
34
|
+
TestWorker.get_shoryuken_options['delete'] = false
|
35
|
+
|
36
|
+
expect(sqs_queue).to_not receive(:batch_delete)
|
37
|
+
|
38
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) {}
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when exception' do
|
42
|
+
it 'does not delete a message' do
|
43
|
+
expect(sqs_queue).to_not receive(:batch_delete)
|
44
|
+
|
45
|
+
expect {
|
46
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise }
|
47
|
+
}.to raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoryuken::Middleware::Server::Timing do
|
4
|
+
let(:sqs_msg) { double AWS::SQS::ReceivedMessage, id: 'fc754df7-9cc2-4c41-96ca-5996a44b771e', body: 'test' }
|
5
|
+
let(:queue) { 'default' }
|
6
|
+
|
7
|
+
xit 'logs timing' do
|
8
|
+
expect(Shoryuken.logger).to receive(:info).with(/started at/)
|
9
|
+
expect(Shoryuken.logger).to receive(:info).with(/completed in/)
|
10
|
+
|
11
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) {}
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when exceeded the `visibility_timeout`' do
|
15
|
+
it 'logs exceeded' do
|
16
|
+
allow(Shoryuken::Client).to receive(:visibility_timeout).and_return(60)
|
17
|
+
allow(subject).to receive(:elapsed).and_return(120000)
|
18
|
+
|
19
|
+
expect(Shoryuken.logger).to receive(:info).with(/started at/)
|
20
|
+
expect(Shoryuken.logger).to receive(:info).with(/completed in/)
|
21
|
+
expect(Shoryuken.logger).to receive(:warn).with('exceeded the queue visibility timeout by 60000 ms')
|
22
|
+
|
23
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when exception' do
|
28
|
+
it 'logs failed in' do
|
29
|
+
expect(Shoryuken.logger).to receive(:info).with(/started at/)
|
30
|
+
expect(Shoryuken.logger).to receive(:info).with(/failed in/)
|
31
|
+
|
32
|
+
expect {
|
33
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise }
|
34
|
+
}.to raise_error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'shoryuken/processor'
|
3
|
+
require 'shoryuken/manager'
|
3
4
|
|
4
5
|
describe Shoryuken::Processor do
|
5
|
-
let(:manager) { double Shoryuken::Manager }
|
6
|
-
let(:sqs_queue) { double
|
7
|
-
let(:queue) { '
|
8
|
-
let(:sqs_msg) { double AWS::SQS::ReceivedMessage, id: 'fc754df7-9cc2-4c41-96ca-5996a44b771e' }
|
6
|
+
let(:manager) { double Shoryuken::Manager, processor_done: nil }
|
7
|
+
let(:sqs_queue) { double AWS::SQS::Queue, visibility_timeout: 30 }
|
8
|
+
let(:queue) { 'default' }
|
9
|
+
let(:sqs_msg) { double AWS::SQS::ReceivedMessage, id: 'fc754df7-9cc2-4c41-96ca-5996a44b771e', body: 'test' }
|
9
10
|
|
10
11
|
subject { described_class.new(manager) }
|
11
12
|
|
@@ -15,27 +16,84 @@ describe Shoryuken::Processor do
|
|
15
16
|
end
|
16
17
|
|
17
18
|
describe '#process' do
|
18
|
-
|
19
|
-
|
19
|
+
it 'parses the body into JSON' do
|
20
|
+
TestWorker.get_shoryuken_options['body_parser'] = :json
|
20
21
|
|
21
|
-
|
22
|
+
body = { 'test' => 'hi' }
|
22
23
|
|
23
|
-
|
24
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, body)
|
25
|
+
|
26
|
+
allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
|
27
|
+
|
28
|
+
subject.process(queue, sqs_msg)
|
24
29
|
end
|
25
30
|
|
26
|
-
it '
|
27
|
-
|
31
|
+
it 'parses the body calling the proc' do
|
32
|
+
TestWorker.get_shoryuken_options['body_parser'] = Proc.new { |sqs_msg| "*#{sqs_msg.body}*" }
|
28
33
|
|
29
|
-
|
34
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, '*test*')
|
35
|
+
|
36
|
+
allow(sqs_msg).to receive(:body).and_return('test')
|
37
|
+
|
38
|
+
subject.process(queue, sqs_msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'parses the body as text' do
|
42
|
+
TestWorker.get_shoryuken_options['body_parser'] = :text
|
43
|
+
|
44
|
+
body = 'test'
|
45
|
+
|
46
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, body)
|
47
|
+
|
48
|
+
allow(sqs_msg).to receive(:body).and_return(body)
|
49
|
+
|
50
|
+
subject.process(queue, sqs_msg)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'parses calling `.parse`' do
|
54
|
+
TestWorker.get_shoryuken_options['body_parser'] = JSON
|
55
|
+
|
56
|
+
body = { 'test' => 'hi' }
|
30
57
|
|
31
|
-
|
58
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, body)
|
59
|
+
|
60
|
+
allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
|
32
61
|
|
33
62
|
subject.process(queue, sqs_msg)
|
34
63
|
end
|
35
64
|
|
65
|
+
context 'when parse errors' do
|
66
|
+
it 'does not fail' do
|
67
|
+
TestWorker.get_shoryuken_options['body_parser'] = :json
|
68
|
+
|
69
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, nil)
|
70
|
+
|
71
|
+
allow(sqs_msg).to receive(:body).and_return('invalid json')
|
72
|
+
|
73
|
+
expect(subject.logger).to receive(:error).with("Error parsing the message body: 757: unexpected token at 'invalid json'\nbody_parser: json\nsqs_msg.body: invalid json")
|
74
|
+
|
75
|
+
subject.process(queue, sqs_msg)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when `object_type: nil`' do
|
80
|
+
it 'parses the body as text' do
|
81
|
+
TestWorker.get_shoryuken_options['body_parser'] = nil
|
82
|
+
|
83
|
+
body = 'test'
|
84
|
+
|
85
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, body)
|
86
|
+
|
87
|
+
allow(sqs_msg).to receive(:body).and_return(body)
|
88
|
+
|
89
|
+
subject.process(queue, sqs_msg)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
36
93
|
context 'when custom middleware' do
|
37
94
|
class WorkerCalledMiddleware
|
38
|
-
def call(worker, queue, sqs_msg)
|
95
|
+
def call(worker, queue, sqs_msg, body)
|
96
|
+
# called is defined with `allow(...).to receive(...)`
|
39
97
|
worker.called(sqs_msg, queue)
|
40
98
|
yield
|
41
99
|
end
|
@@ -60,33 +118,33 @@ describe Shoryuken::Processor do
|
|
60
118
|
it 'invokes middleware' do
|
61
119
|
expect(manager).to receive(:processor_done).with(queue, subject)
|
62
120
|
|
63
|
-
expect_any_instance_of(
|
64
|
-
expect_any_instance_of(
|
121
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
122
|
+
expect_any_instance_of(TestWorker).to receive(:called).with(sqs_msg, queue)
|
65
123
|
|
66
124
|
subject.process(queue, sqs_msg)
|
67
125
|
end
|
68
126
|
end
|
69
127
|
|
70
128
|
it 'performs with delete' do
|
71
|
-
|
129
|
+
TestWorker.get_shoryuken_options['delete'] = true
|
72
130
|
|
73
131
|
expect(manager).to receive(:processor_done).with(queue, subject)
|
74
132
|
|
75
|
-
expect_any_instance_of(
|
133
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
76
134
|
|
77
|
-
expect(
|
135
|
+
expect(sqs_queue).to receive(:batch_delete).with(sqs_msg)
|
78
136
|
|
79
137
|
subject.process(queue, sqs_msg)
|
80
138
|
end
|
81
139
|
|
82
140
|
it 'performs without delete' do
|
83
|
-
|
141
|
+
TestWorker.get_shoryuken_options['delete'] = false
|
84
142
|
|
85
143
|
expect(manager).to receive(:processor_done).with(queue, subject)
|
86
144
|
|
87
|
-
expect_any_instance_of(
|
145
|
+
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
88
146
|
|
89
|
-
expect(
|
147
|
+
expect(sqs_queue).to_not receive(:batch_delete)
|
90
148
|
|
91
149
|
subject.process(queue, sqs_msg)
|
92
150
|
end
|
@@ -1,28 +1,42 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'Shoryuken::Worker' do
|
4
|
+
let(:sqs_queue) { double 'SQS Queue' }
|
5
|
+
let(:queue) { 'default' }
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
include Shoryuken::Worker
|
7
|
+
before do
|
8
|
+
allow(Shoryuken::Client).to receive(:queues).with(queue).and_return(sqs_queue)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
describe '.perform_async' do
|
12
|
+
it 'enqueues a message' do
|
13
|
+
expect(sqs_queue).to receive(:send_message).with('message', {})
|
14
|
+
|
15
|
+
TestWorker.perform_async('message')
|
16
|
+
end
|
12
17
|
|
13
|
-
|
18
|
+
it 'enqueues a message with options' do
|
19
|
+
expect(sqs_queue).to receive(:send_message).with('delayed message', delay_seconds: 60)
|
20
|
+
|
21
|
+
TestWorker.perform_async('delayed message', delay_seconds: 60)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.shoryuken_options' do
|
26
|
+
it 'registers a worker' do
|
27
|
+
expect(Shoryuken.workers['default']).to eq TestWorker
|
14
28
|
end
|
15
29
|
|
16
30
|
it 'accepts a block as queue name' do
|
17
31
|
$queue_prefix = 'production'
|
18
32
|
|
19
|
-
class
|
33
|
+
class NewTestWorker
|
20
34
|
include Shoryuken::Worker
|
21
35
|
|
22
|
-
shoryuken_options queue: ->{ "#{$queue_prefix}
|
36
|
+
shoryuken_options queue: ->{ "#{$queue_prefix}_default" }
|
23
37
|
end
|
24
38
|
|
25
|
-
expect(Shoryuken.workers['
|
39
|
+
expect(Shoryuken.workers['production_default']).to eq NewTestWorker
|
26
40
|
end
|
27
41
|
end
|
28
42
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,8 +2,8 @@ require 'bundler/setup'
|
|
2
2
|
Bundler.setup
|
3
3
|
|
4
4
|
require 'pry-byebug'
|
5
|
-
require 'shoryuken'
|
6
5
|
require 'celluloid'
|
6
|
+
require 'shoryuken'
|
7
7
|
|
8
8
|
options_file = File.join(File.expand_path('../..', __FILE__), 'shoryuken.yml')
|
9
9
|
|
@@ -18,6 +18,14 @@ end
|
|
18
18
|
Shoryuken.logger.level = Logger::UNKNOWN
|
19
19
|
Celluloid.logger.level = Logger::UNKNOWN
|
20
20
|
|
21
|
+
class TestWorker
|
22
|
+
include Shoryuken::Worker
|
23
|
+
|
24
|
+
shoryuken_options queue: 'default'
|
25
|
+
|
26
|
+
def perform(sqs_msg, body); end
|
27
|
+
end
|
28
|
+
|
21
29
|
RSpec.configure do |config|
|
22
30
|
config.filter_run_excluding slow: true unless ENV['SPEC_ALL']
|
23
31
|
|
@@ -38,5 +46,8 @@ RSpec.configure do |config|
|
|
38
46
|
Shoryuken.options[:timeout] = 1
|
39
47
|
|
40
48
|
Shoryuken.options[:aws] = {}
|
49
|
+
|
50
|
+
TestWorker.get_shoryuken_options.clear
|
51
|
+
TestWorker.get_shoryuken_options['queue'] = 'default'
|
41
52
|
end
|
42
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shoryuken
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pablo Cantero
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: multi_json
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - '>='
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :runtime
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - '>='
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
97
|
description: Shoryuken is a super efficient AWS SQS thread based message processor
|
112
98
|
email:
|
113
99
|
- pablo@pablocantero.com
|
@@ -125,9 +111,9 @@ files:
|
|
125
111
|
- Rakefile
|
126
112
|
- bin/shoryuken
|
127
113
|
- examples/all.rb
|
128
|
-
- examples/
|
129
|
-
- examples/
|
130
|
-
- examples/
|
114
|
+
- examples/default_worker.rb
|
115
|
+
- examples/high_priority_worker.rb
|
116
|
+
- examples/low_priority_worker.rb
|
131
117
|
- lib/shoryuken.rb
|
132
118
|
- lib/shoryuken/cli.rb
|
133
119
|
- lib/shoryuken/client.rb
|
@@ -137,8 +123,8 @@ files:
|
|
137
123
|
- lib/shoryuken/logging.rb
|
138
124
|
- lib/shoryuken/manager.rb
|
139
125
|
- lib/shoryuken/middleware/chain.rb
|
140
|
-
- lib/shoryuken/middleware/server/
|
141
|
-
- lib/shoryuken/middleware/server/
|
126
|
+
- lib/shoryuken/middleware/server/auto_delete.rb
|
127
|
+
- lib/shoryuken/middleware/server/timing.rb
|
142
128
|
- lib/shoryuken/processor.rb
|
143
129
|
- lib/shoryuken/util.rb
|
144
130
|
- lib/shoryuken/version.rb
|
@@ -151,7 +137,8 @@ files:
|
|
151
137
|
- spec/shoryuken/fetcher_spec.rb
|
152
138
|
- spec/shoryuken/manager_spec.rb
|
153
139
|
- spec/shoryuken/middleware/chain_spec.rb
|
154
|
-
- spec/shoryuken/middleware/server/
|
140
|
+
- spec/shoryuken/middleware/server/auto_delete_spec.rb
|
141
|
+
- spec/shoryuken/middleware/server/timing_spec.rb
|
155
142
|
- spec/shoryuken/processor_spec.rb
|
156
143
|
- spec/shoryuken/util_spec.rb
|
157
144
|
- spec/shoryuken/worker_spec.rb
|
@@ -187,7 +174,8 @@ test_files:
|
|
187
174
|
- spec/shoryuken/fetcher_spec.rb
|
188
175
|
- spec/shoryuken/manager_spec.rb
|
189
176
|
- spec/shoryuken/middleware/chain_spec.rb
|
190
|
-
- spec/shoryuken/middleware/server/
|
177
|
+
- spec/shoryuken/middleware/server/auto_delete_spec.rb
|
178
|
+
- spec/shoryuken/middleware/server/timing_spec.rb
|
191
179
|
- spec/shoryuken/processor_spec.rb
|
192
180
|
- spec/shoryuken/util_spec.rb
|
193
181
|
- spec/shoryuken/worker_spec.rb
|
data/examples/sidekiq_worker.rb
DELETED
data/examples/uppercut_worker.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module Shoryuken
|
2
|
-
module Middleware
|
3
|
-
module Server
|
4
|
-
class Delete
|
5
|
-
def call(worker, queue, sqs_msg)
|
6
|
-
yield
|
7
|
-
|
8
|
-
# auto_delete is deprecated
|
9
|
-
delete = worker.class.get_shoryuken_options['delete'] || worker.class.get_shoryuken_options['auto_delete']
|
10
|
-
|
11
|
-
Array(sqs_msg).each(&:delete) if delete
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Shoryuken::Middleware::Server::Delete do
|
4
|
-
let(:sqs_msg) { double 'SQS msg' }
|
5
|
-
|
6
|
-
before do
|
7
|
-
DeleteWorker.get_shoryuken_options['delete'] = true
|
8
|
-
end
|
9
|
-
|
10
|
-
class DeleteWorker
|
11
|
-
include Shoryuken::Worker
|
12
|
-
|
13
|
-
shoryuken_options queue: 'delete', delete: true
|
14
|
-
|
15
|
-
def perform; end
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'deletes a message' do
|
19
|
-
expect(sqs_msg).to receive(:delete)
|
20
|
-
|
21
|
-
subject.call(DeleteWorker.new, 'delete', sqs_msg) {}
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'deletes a batch' do
|
25
|
-
sqs_msg2 = double
|
26
|
-
sqs_msg3 = double
|
27
|
-
|
28
|
-
expect(sqs_msg).to receive(:delete)
|
29
|
-
expect(sqs_msg2).to receive(:delete)
|
30
|
-
expect(sqs_msg3).to receive(:delete)
|
31
|
-
|
32
|
-
subject.call(DeleteWorker.new, 'delete', [sqs_msg, sqs_msg2, sqs_msg3]) {}
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'does not delete a message' do
|
36
|
-
DeleteWorker.get_shoryuken_options['delete'] = false
|
37
|
-
|
38
|
-
expect(sqs_msg).to_not receive(:delete)
|
39
|
-
|
40
|
-
subject.call(DeleteWorker.new, 'delete', sqs_msg) {}
|
41
|
-
end
|
42
|
-
|
43
|
-
context 'when exception' do
|
44
|
-
it 'does not delete a message' do
|
45
|
-
expect(sqs_msg).to_not receive(:delete)
|
46
|
-
|
47
|
-
expect {
|
48
|
-
subject.call(DeleteWorker.new, 'delete', sqs_msg) { raise }
|
49
|
-
}.to raise_error
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|