shoryuken 3.1.8 → 3.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +12 -2
- data/CHANGELOG.md +34 -0
- data/Gemfile +5 -3
- data/Gemfile.aws-sdk-core-v2 +13 -0
- data/bin/shoryuken +1 -0
- data/lib/shoryuken/body_parser.rb +27 -0
- data/lib/shoryuken/fetcher.rb +27 -6
- data/lib/shoryuken/manager.rb +5 -2
- data/lib/shoryuken/middleware/chain.rb +4 -0
- data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +2 -5
- data/lib/shoryuken/middleware/server/timing.rb +12 -14
- data/lib/shoryuken/options.rb +9 -0
- data/lib/shoryuken/processor.rb +5 -21
- data/lib/shoryuken/util.rb +2 -2
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken/worker/default_executor.rb +33 -0
- data/lib/shoryuken/worker/inline_executor.rb +28 -0
- data/lib/shoryuken/worker.rb +68 -31
- data/lib/shoryuken.rb +11 -0
- data/shoryuken.gemspec +1 -1
- data/spec/shoryuken/body_parser_spec.rb +89 -0
- data/spec/shoryuken/fetcher_spec.rb +16 -0
- data/spec/shoryuken/manager_spec.rb +2 -2
- data/spec/shoryuken/middleware/chain_spec.rb +16 -4
- data/spec/shoryuken/processor_spec.rb +15 -97
- data/spec/shoryuken/util_spec.rb +25 -1
- data/spec/shoryuken/worker/default_executor_spec.rb +100 -0
- data/spec/shoryuken/worker/inline_executor_spec.rb +23 -0
- data/spec/shoryuken/worker_spec.rb +32 -91
- metadata +15 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f74e5fbb599fe5bbe41bed5fd542c0c1fdcc2d35
|
|
4
|
+
data.tar.gz: 6099d42682b5e2a1797d7cdbdc7bf27b344b692c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f076e8f427f39ca92be4f27be819350d90270ce9e695d1173a6944b82d16680d11afd78a0075dd549e0a2c6031e6d5708c306cb245c4d7dfcc69d8a5e7151bc7
|
|
7
|
+
data.tar.gz: 2fd34c84e6260df3c35427ffb27d3d067fc1ea11469609d61e8eedd465e4516d75e052079b5195ede7c7917ad3c97bb39c5440bc5436ae3ab2581f3fb72bad31
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
+
|
|
2
3
|
rvm:
|
|
3
4
|
- 2.0.0
|
|
4
5
|
- 2.1.10
|
|
@@ -11,9 +12,18 @@ notifications:
|
|
|
11
12
|
on_success: change
|
|
12
13
|
on_failure: always
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
gemfile:
|
|
16
|
+
- Gemfile
|
|
17
|
+
- Gemfile.aws-sdk-core-v2
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
- SPEC_ALL=true
|
|
21
|
+
|
|
22
|
+
script: bundle exec rspec spec
|
|
23
|
+
|
|
15
24
|
before_install:
|
|
16
|
-
|
|
25
|
+
- gem update bundler
|
|
26
|
+
|
|
17
27
|
after_success:
|
|
18
28
|
- bundle exec codeclimate-test-reporter
|
|
19
29
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
## [v3.2.0] - 2018-01-03
|
|
2
|
+
|
|
3
|
+
- Preserve parent worker class options
|
|
4
|
+
- [#451](https://github.com/phstc/shoryuken/pull/451)
|
|
5
|
+
|
|
6
|
+
- Add -t (shutdown timeout) option to CL
|
|
7
|
+
- [#449](https://github.com/phstc/shoryuken/pull/449)
|
|
8
|
+
|
|
9
|
+
- Support inline (Active Job like) for standard workers
|
|
10
|
+
- [#448](https://github.com/phstc/shoryuken/pull/448)
|
|
11
|
+
|
|
12
|
+
## [v3.1.12] - 2017-09-25
|
|
13
|
+
|
|
14
|
+
- Reduce fetch log verbosity
|
|
15
|
+
- [#436](https://github.com/phstc/shoryuken/pull/436)
|
|
16
|
+
|
|
17
|
+
## [v3.1.11] - 2017-09-02
|
|
18
|
+
|
|
19
|
+
- Auto retry (up to 3 times) fetch errors
|
|
20
|
+
- [#429](https://github.com/phstc/shoryuken/pull/429)
|
|
21
|
+
|
|
22
|
+
## [v3.1.10] - 2017-09-02
|
|
23
|
+
|
|
24
|
+
- Make Shoryuken compatible with AWS SDK 3 and 2
|
|
25
|
+
- [#433](https://github.com/phstc/shoryuken/pull/433)
|
|
26
|
+
|
|
27
|
+
## [v3.1.9] - 2017-08-24
|
|
28
|
+
|
|
29
|
+
- Add support for adding a middleware to the front of chain
|
|
30
|
+
- [#427](https://github.com/phstc/shoryuken/pull/427)
|
|
31
|
+
|
|
32
|
+
- Add support for dispatch fire event
|
|
33
|
+
- [#426](https://github.com/phstc/shoryuken/pull/426)
|
|
34
|
+
|
|
1
35
|
## [v3.1.8] - 2017-08-17
|
|
2
36
|
|
|
3
37
|
- Make Polling strategy backward compatibility
|
data/Gemfile
CHANGED
|
@@ -4,9 +4,11 @@ source 'https://rubygems.org'
|
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
6
|
group :test do
|
|
7
|
-
gem 'activejob'
|
|
7
|
+
gem 'activejob', '~> 4'
|
|
8
|
+
gem 'aws-sdk-core', '~> 3'
|
|
9
|
+
gem 'aws-sdk-sqs'
|
|
8
10
|
gem 'codeclimate-test-reporter', require: nil
|
|
9
|
-
gem 'simplecov'
|
|
10
|
-
gem 'multi_xml'
|
|
11
11
|
gem 'httparty'
|
|
12
|
+
gem 'multi_xml'
|
|
13
|
+
gem 'simplecov'
|
|
12
14
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in shoryuken.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
group :test do
|
|
7
|
+
gem 'activejob', '~> 4'
|
|
8
|
+
gem 'aws-sdk-core', '~> 2'
|
|
9
|
+
gem 'codeclimate-test-reporter', require: nil
|
|
10
|
+
gem 'httparty'
|
|
11
|
+
gem 'multi_xml'
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
end
|
data/bin/shoryuken
CHANGED
|
@@ -21,6 +21,7 @@ module Shoryuken
|
|
|
21
21
|
method_option :daemon, aliases: '-d', type: :boolean, desc: 'Daemonize process'
|
|
22
22
|
method_option :queues, aliases: '-q', type: :array, desc: 'Queues to process with optional weights'
|
|
23
23
|
method_option :require, aliases: '-r', type: :string, desc: 'Dir or path of the workers'
|
|
24
|
+
method_option :timeout, aliases: '-t', type: :numeric, desc: 'Hard shutdown timeout'
|
|
24
25
|
method_option :config, aliases: '-C', type: :string, desc: 'Path to config file'
|
|
25
26
|
method_option :config_file, type: :string, desc: 'Path to config file (backwards compatibility)'
|
|
26
27
|
method_option :rails, aliases: '-R', type: :boolean, desc: 'Load Rails'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Shoryuken
|
|
2
|
+
class BodyParser
|
|
3
|
+
class << self
|
|
4
|
+
def parse(worker_class, sqs_msg)
|
|
5
|
+
body_parser = worker_class.get_shoryuken_options['body_parser']
|
|
6
|
+
|
|
7
|
+
case body_parser
|
|
8
|
+
when :json
|
|
9
|
+
JSON.parse(sqs_msg.body)
|
|
10
|
+
when Proc
|
|
11
|
+
body_parser.call(sqs_msg)
|
|
12
|
+
when :text, nil
|
|
13
|
+
sqs_msg.body
|
|
14
|
+
else
|
|
15
|
+
if body_parser.respond_to?(:parse)
|
|
16
|
+
# JSON.parse
|
|
17
|
+
body_parser.parse(sqs_msg.body)
|
|
18
|
+
elsif body_parser.respond_to?(:load)
|
|
19
|
+
# see https://github.com/phstc/shoryuken/pull/91
|
|
20
|
+
# JSON.load
|
|
21
|
+
body_parser.load(sqs_msg.body)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/shoryuken/fetcher.rb
CHANGED
|
@@ -9,20 +9,41 @@ module Shoryuken
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def fetch(queue, limit)
|
|
12
|
-
|
|
12
|
+
fetch_with_auto_retry(3) do
|
|
13
|
+
started_at = Time.now
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
logger.debug { "Looking for new messages in #{queue}" }
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
sqs_msgs = Array(receive_messages(queue, [FETCH_LIMIT, limit].min))
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
logger.debug { "Found #{sqs_msgs.size} messages for #{queue.name}" } unless sqs_msgs.empty?
|
|
20
|
+
logger.debug { "Fetcher for #{queue} completed in #{elapsed(started_at)} ms" }
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
sqs_msgs
|
|
23
|
+
end
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
private
|
|
25
27
|
|
|
28
|
+
def fetch_with_auto_retry(max_attempts, &block)
|
|
29
|
+
attempts = 0
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
yield
|
|
33
|
+
rescue => ex
|
|
34
|
+
# Tries to auto retry connectivity errors
|
|
35
|
+
raise if attempts >= max_attempts
|
|
36
|
+
|
|
37
|
+
attempts += 1
|
|
38
|
+
|
|
39
|
+
logger.debug { "Retrying fetch attempt #{attempts} for #{ex.message}" }
|
|
40
|
+
|
|
41
|
+
sleep((1..5).to_a.sample)
|
|
42
|
+
|
|
43
|
+
retry
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
26
47
|
def receive_messages(queue, limit)
|
|
27
48
|
options = receive_options(queue)
|
|
28
49
|
|
data/lib/shoryuken/manager.rb
CHANGED
|
@@ -12,6 +12,7 @@ module Shoryuken
|
|
|
12
12
|
@max_processors = concurrency
|
|
13
13
|
@busy_processors = Concurrent::AtomicFixnum.new(0)
|
|
14
14
|
@executor = executor
|
|
15
|
+
@running = Concurrent::AtomicBoolean.new(true)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def start
|
|
@@ -21,7 +22,7 @@ module Shoryuken
|
|
|
21
22
|
private
|
|
22
23
|
|
|
23
24
|
def running?
|
|
24
|
-
@executor.running?
|
|
25
|
+
@running.true? && @executor.running?
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
def dispatch_loop
|
|
@@ -37,7 +38,7 @@ module Shoryuken
|
|
|
37
38
|
return sleep(MIN_DISPATCH_INTERVAL)
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
fire_event(:dispatch)
|
|
41
|
+
fire_event(:dispatch, false, queue_name: queue.name)
|
|
41
42
|
|
|
42
43
|
logger.debug { "Ready: #{ready}, Busy: #{busy}, Active Queues: #{@polling_strategy.active_queues}" }
|
|
43
44
|
|
|
@@ -104,6 +105,8 @@ module Shoryuken
|
|
|
104
105
|
logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
|
|
105
106
|
|
|
106
107
|
Process.kill('USR1', Process.pid)
|
|
108
|
+
|
|
109
|
+
@running.make_false
|
|
107
110
|
end
|
|
108
111
|
end
|
|
109
112
|
end
|
|
@@ -61,6 +61,10 @@ module Shoryuken
|
|
|
61
61
|
entries << Entry.new(klass, *args) unless exists?(klass)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def prepend(klass, *args)
|
|
65
|
+
entries.insert(0, Entry.new(klass, *args)) unless exists?(klass)
|
|
66
|
+
end
|
|
67
|
+
|
|
64
68
|
def insert_before(oldklass, newklass, *args)
|
|
65
69
|
i = entries.index { |entry| entry.klass == newklass }
|
|
66
70
|
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
|
@@ -31,16 +31,13 @@ module Shoryuken
|
|
|
31
31
|
Concurrent::TimerTask.new(execution_interval: queue_visibility_timeout - EXTEND_UPFRONT_SECONDS) do
|
|
32
32
|
begin
|
|
33
33
|
logger.debug do
|
|
34
|
-
"Extending message #{
|
|
35
|
-
"visibility timeout by #{queue_visibility_timeout}s."
|
|
34
|
+
"Extending message #{queue}/#{sqs_msg.message_id} visibility timeout by #{queue_visibility_timeout}s"
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
sqs_msg.change_visibility(visibility_timeout: queue_visibility_timeout)
|
|
39
38
|
rescue => ex
|
|
40
39
|
logger.error do
|
|
41
|
-
|
|
42
|
-
"#{worker_name(worker.class, sqs_msg, body)}/#{queue}/#{sqs_msg.message_id} " \
|
|
43
|
-
"visibility timeout. Error: #{ex.message}"
|
|
40
|
+
"Could not auto extend the message #{queue}/#{sqs_msg.message_id} visibility timeout. Error: #{ex.message}"
|
|
44
41
|
end
|
|
45
42
|
end
|
|
46
43
|
end
|
|
@@ -5,25 +5,23 @@ module Shoryuken
|
|
|
5
5
|
include Util
|
|
6
6
|
|
|
7
7
|
def call(worker, queue, sqs_msg, body)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
started_at = Time.now
|
|
8
|
+
begin
|
|
9
|
+
started_at = Time.now
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
logger.info { "started at #{started_at}" }
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
yield
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
total_time = elapsed(started_at)
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
logger.info { "completed in: #{total_time} ms" }
|
|
23
|
-
rescue
|
|
24
|
-
logger.info { "failed in: #{elapsed(started_at)} ms" }
|
|
25
|
-
raise
|
|
17
|
+
if (total_time / 1000.0) > (timeout = Shoryuken::Client.queues(queue).visibility_timeout)
|
|
18
|
+
logger.warn { "exceeded the queue visibility timeout by #{total_time - (timeout * 1000)} ms" }
|
|
26
19
|
end
|
|
20
|
+
|
|
21
|
+
logger.info { "completed in: #{total_time} ms" }
|
|
22
|
+
rescue
|
|
23
|
+
logger.info { "failed in: #{elapsed(started_at)} ms" }
|
|
24
|
+
raise
|
|
27
25
|
end
|
|
28
26
|
end
|
|
29
27
|
end
|
data/lib/shoryuken/options.rb
CHANGED
|
@@ -21,6 +21,7 @@ module Shoryuken
|
|
|
21
21
|
@@sqs_client_receive_message_opts = {}
|
|
22
22
|
@@start_callback = nil
|
|
23
23
|
@@stop_callback = nil
|
|
24
|
+
@@worker_executor = Worker::DefaultExecutor
|
|
24
25
|
|
|
25
26
|
class << self
|
|
26
27
|
def active_job?
|
|
@@ -56,6 +57,14 @@ module Shoryuken
|
|
|
56
57
|
@@worker_registry = worker_registry
|
|
57
58
|
end
|
|
58
59
|
|
|
60
|
+
def worker_executor
|
|
61
|
+
@@worker_executor
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def worker_executor=(worker_executor)
|
|
65
|
+
@@worker_executor = worker_executor
|
|
66
|
+
end
|
|
67
|
+
|
|
59
68
|
def polling_strategy(group)
|
|
60
69
|
strategy = (group == 'default' ? options : options[:groups].to_h[group]).to_h[:polling_strategy]
|
|
61
70
|
|
data/lib/shoryuken/processor.rb
CHANGED
|
@@ -16,8 +16,10 @@ module Shoryuken
|
|
|
16
16
|
def process
|
|
17
17
|
return logger.error { "No worker found for #{queue}" } unless worker
|
|
18
18
|
|
|
19
|
-
worker.class
|
|
20
|
-
worker.
|
|
19
|
+
Shoryuken::Logging.with_context("#{worker_name(worker.class, sqs_msg, body)}/#{queue}/#{sqs_msg.message_id}") do
|
|
20
|
+
worker.class.server_middleware.invoke(worker, queue, sqs_msg, body) do
|
|
21
|
+
worker.perform(sqs_msg, body)
|
|
22
|
+
end
|
|
21
23
|
end
|
|
22
24
|
rescue Exception => ex
|
|
23
25
|
logger.error { "Processor failed: #{ex.message}" }
|
|
@@ -41,25 +43,7 @@ module Shoryuken
|
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
def parse_body(sqs_msg)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
case body_parser
|
|
47
|
-
when :json
|
|
48
|
-
JSON.parse(sqs_msg.body)
|
|
49
|
-
when Proc
|
|
50
|
-
body_parser.call(sqs_msg)
|
|
51
|
-
when :text, nil
|
|
52
|
-
sqs_msg.body
|
|
53
|
-
else
|
|
54
|
-
if body_parser.respond_to?(:parse)
|
|
55
|
-
# JSON.parse
|
|
56
|
-
body_parser.parse(sqs_msg.body)
|
|
57
|
-
elsif body_parser.respond_to?(:load)
|
|
58
|
-
# see https://github.com/phstc/shoryuken/pull/91
|
|
59
|
-
# JSON.load
|
|
60
|
-
body_parser.load(sqs_msg.body)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
46
|
+
BodyParser.parse(worker_class, sqs_msg)
|
|
63
47
|
end
|
|
64
48
|
end
|
|
65
49
|
end
|
data/lib/shoryuken/util.rb
CHANGED
|
@@ -4,13 +4,13 @@ module Shoryuken
|
|
|
4
4
|
Shoryuken.logger
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
def fire_event(event, reverse = false)
|
|
7
|
+
def fire_event(event, reverse = false, event_options = {})
|
|
8
8
|
logger.debug { "Firing '#{event}' lifecycle event" }
|
|
9
9
|
arr = Shoryuken.options[:lifecycle_events][event]
|
|
10
10
|
arr.reverse! if reverse
|
|
11
11
|
arr.each do |block|
|
|
12
12
|
begin
|
|
13
|
-
block.call
|
|
13
|
+
block.call(event_options)
|
|
14
14
|
rescue => ex
|
|
15
15
|
logger.warn(event: event)
|
|
16
16
|
logger.warn "#{ex.class.name}: #{ex.message}"
|
data/lib/shoryuken/version.rb
CHANGED
|
@@ -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,28 @@
|
|
|
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
|
+
worker_class.new.perform(sqs_msg, BodyParser.parse(worker_class, sqs_msg))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def perform_in(worker_class, _interval, body, options = {})
|
|
23
|
+
perform_async(worker_class, body, options)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/shoryuken/worker.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
26
|
+
self.shoryuken_options_hash = get_shoryuken_options.merge(stringify_keys(opts || {}))
|
|
44
27
|
normalize_worker_queue!
|
|
45
28
|
end
|
|
46
29
|
|
|
@@ -57,33 +40,87 @@ module Shoryuken
|
|
|
57
40
|
end
|
|
58
41
|
|
|
59
42
|
def get_shoryuken_options # :nodoc:
|
|
60
|
-
|
|
43
|
+
shoryuken_options_hash || Shoryuken.default_worker_options
|
|
61
44
|
end
|
|
62
45
|
|
|
63
46
|
def stringify_keys(hash) # :nodoc:
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
66
104
|
end
|
|
67
|
-
hash
|
|
68
105
|
end
|
|
69
106
|
|
|
70
107
|
private
|
|
71
108
|
|
|
72
109
|
def normalize_worker_queue!
|
|
73
|
-
queue =
|
|
110
|
+
queue = shoryuken_options_hash['queue']
|
|
74
111
|
if queue.respond_to?(:call)
|
|
75
112
|
queue = queue.call
|
|
76
|
-
|
|
113
|
+
shoryuken_options_hash['queue'] = queue
|
|
77
114
|
end
|
|
78
115
|
|
|
79
|
-
case
|
|
116
|
+
case shoryuken_options_hash['queue']
|
|
80
117
|
when Array
|
|
81
|
-
|
|
118
|
+
shoryuken_options_hash['queue'].map!(&:to_s)
|
|
82
119
|
when Symbol
|
|
83
|
-
|
|
120
|
+
shoryuken_options_hash['queue'] = shoryuken_options_hash['queue'].to_s
|
|
84
121
|
end
|
|
85
122
|
|
|
86
|
-
[
|
|
123
|
+
[shoryuken_options_hash['queue']].flatten.compact.each(&method(:register_worker))
|
|
87
124
|
end
|
|
88
125
|
|
|
89
126
|
def register_worker(queue)
|
data/lib/shoryuken.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
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'
|
|
6
11
|
require 'forwardable'
|
|
@@ -14,6 +19,8 @@ require 'shoryuken/queue'
|
|
|
14
19
|
require 'shoryuken/message'
|
|
15
20
|
require 'shoryuken/client'
|
|
16
21
|
require 'shoryuken/worker'
|
|
22
|
+
require 'shoryuken/worker/default_executor'
|
|
23
|
+
require 'shoryuken/worker/inline_executor'
|
|
17
24
|
require 'shoryuken/worker_registry'
|
|
18
25
|
require 'shoryuken/default_worker_registry'
|
|
19
26
|
require 'shoryuken/middleware/chain'
|
|
@@ -27,9 +34,11 @@ require 'shoryuken/polling/strict_priority'
|
|
|
27
34
|
require 'shoryuken/manager'
|
|
28
35
|
require 'shoryuken/launcher'
|
|
29
36
|
require 'shoryuken/processor'
|
|
37
|
+
require 'shoryuken/body_parser'
|
|
30
38
|
require 'shoryuken/fetcher'
|
|
31
39
|
require 'shoryuken/options'
|
|
32
40
|
|
|
41
|
+
|
|
33
42
|
module Shoryuken
|
|
34
43
|
extend SingleForwardable
|
|
35
44
|
|
|
@@ -42,6 +51,8 @@ module Shoryuken
|
|
|
42
51
|
:ungrouped_queues,
|
|
43
52
|
:worker_registry,
|
|
44
53
|
:worker_registry=,
|
|
54
|
+
:worker_executor,
|
|
55
|
+
:worker_executor=,
|
|
45
56
|
:polling_strategy,
|
|
46
57
|
:start_callback,
|
|
47
58
|
:start_callback=,
|
data/shoryuken.gemspec
CHANGED
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
spec.add_development_dependency 'pry-byebug'
|
|
24
24
|
spec.add_development_dependency 'dotenv'
|
|
25
25
|
|
|
26
|
-
spec.add_dependency 'aws-sdk-core', '
|
|
26
|
+
spec.add_dependency 'aws-sdk-core', '>= 2'
|
|
27
27
|
spec.add_dependency 'concurrent-ruby'
|
|
28
28
|
spec.add_dependency 'thor'
|
|
29
29
|
end
|