shoryuken 3.0.11 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +13 -2
- data/Gemfile +1 -0
- data/README.md +15 -110
- data/bin/cli/sqs.rb +7 -0
- data/lib/shoryuken.rb +39 -173
- data/lib/shoryuken/default_worker_registry.rb +2 -2
- data/lib/shoryuken/environment_loader.rb +25 -9
- data/lib/shoryuken/fetcher.rb +17 -16
- data/lib/shoryuken/launcher.rb +86 -7
- data/lib/shoryuken/manager.rb +38 -79
- data/lib/shoryuken/options.rb +192 -0
- data/lib/shoryuken/polling/base.rb +67 -0
- data/lib/shoryuken/polling/strict_priority.rb +77 -0
- data/lib/shoryuken/polling/weighted_round_robin.rb +66 -0
- data/lib/shoryuken/processor.rb +21 -18
- data/lib/shoryuken/runner.rb +3 -15
- data/lib/shoryuken/version.rb +1 -1
- data/spec/integration/launcher_spec.rb +12 -6
- data/spec/shoryuken/environment_loader_spec.rb +3 -12
- data/spec/shoryuken/fetcher_spec.rb +30 -15
- data/spec/shoryuken/manager_spec.rb +9 -17
- data/spec/shoryuken/options_spec.rb +100 -0
- data/spec/shoryuken/{polling_spec.rb → polling/strict_priority_spec.rb} +1 -100
- data/spec/shoryuken/polling/weighted_round_robin_spec.rb +99 -0
- data/spec/shoryuken/processor_spec.rb +20 -39
- data/spec/shoryuken/runner_spec.rb +3 -4
- data/spec/shoryuken_spec.rb +0 -59
- data/spec/spec_helper.rb +7 -2
- metadata +12 -5
- data/lib/shoryuken/polling.rb +0 -204
@@ -24,7 +24,7 @@ module Shoryuken
|
|
24
24
|
@workers[queue]
|
25
25
|
end
|
26
26
|
|
27
|
-
worker_class.new
|
27
|
+
worker_class.new if worker_class
|
28
28
|
end
|
29
29
|
|
30
30
|
def queues
|
@@ -34,7 +34,7 @@ module Shoryuken
|
|
34
34
|
def register_worker(queue, clazz)
|
35
35
|
if (worker_class = @workers[queue])
|
36
36
|
if worker_class.get_shoryuken_options['batch'] == true || clazz.get_shoryuken_options['batch'] == true
|
37
|
-
fail ArgumentError, "Could not register #{clazz} for
|
37
|
+
fail ArgumentError, "Could not register #{clazz} for #{queue}, "\
|
38
38
|
"because #{worker_class} is already registered for this queue, "\
|
39
39
|
"and Shoryuken doesn't support a batchable worker for a queue with multiple workers"
|
40
40
|
end
|
@@ -44,7 +44,11 @@ module Shoryuken
|
|
44
44
|
|
45
45
|
fail ArgumentError, "The supplied config file #{path} does not exist" unless File.exist?(path)
|
46
46
|
|
47
|
-
YAML.load(ERB.new(IO.read(path)).result)
|
47
|
+
if result = YAML.load(ERB.new(IO.read(path)).result)
|
48
|
+
result.deep_symbolize_keys
|
49
|
+
else
|
50
|
+
{}
|
51
|
+
end
|
48
52
|
end
|
49
53
|
|
50
54
|
def initialize_logger
|
@@ -96,13 +100,24 @@ module Shoryuken
|
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
99
|
-
def parse_queue(queue, weight = nil)
|
100
|
-
Shoryuken.add_queue(queue, [weight.to_i, 1].max)
|
103
|
+
def parse_queue(queue, weight = nil, group)
|
104
|
+
Shoryuken.add_queue(queue, [weight.to_i, 1].max, group)
|
101
105
|
end
|
102
106
|
|
103
107
|
def parse_queues
|
104
|
-
Shoryuken.options[:queues].to_a.
|
105
|
-
|
108
|
+
if Shoryuken.options[:queues].to_a.any?
|
109
|
+
Shoryuken.add_group('default', Shoryuken.options.fetch(:concurrency, 25))
|
110
|
+
|
111
|
+
Shoryuken.options[:queues].to_a.each do |queue, weight|
|
112
|
+
parse_queue(queue, weight, 'default')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
Shoryuken.options[:groups].to_a.each do |group, options|
|
117
|
+
Shoryuken.add_group(group, options.fetch(:concurrency, 25))
|
118
|
+
options[:queues].to_a.each do |queue, weight|
|
119
|
+
parse_queue(queue, weight, group)
|
120
|
+
end
|
106
121
|
end
|
107
122
|
end
|
108
123
|
|
@@ -119,10 +134,11 @@ module Shoryuken
|
|
119
134
|
end
|
120
135
|
|
121
136
|
def validate_queues
|
122
|
-
return Shoryuken.logger.warn { 'No queues supplied' } if Shoryuken.
|
137
|
+
return Shoryuken.logger.warn { 'No queues supplied' } if Shoryuken.ungrouped_queues.empty?
|
138
|
+
|
123
139
|
non_existent_queues = []
|
124
140
|
|
125
|
-
Shoryuken.
|
141
|
+
Shoryuken.ungrouped_queues.uniq.each do |queue|
|
126
142
|
begin
|
127
143
|
Shoryuken::Client.queues(queue)
|
128
144
|
rescue Aws::Errors::NoSuchEndpointError, Aws::SQS::Errors::NonExistentQueue
|
@@ -134,14 +150,14 @@ module Shoryuken
|
|
134
150
|
|
135
151
|
fail(
|
136
152
|
ArgumentError,
|
137
|
-
"The specified queue(s) #{non_existent_queues.join(', ')} do not exist.\
|
153
|
+
"The specified queue(s) #{non_existent_queues.join(', ')} do not exist.\nTry 'shoryuken sqs create QUEUE-NAME' for creating a queue with default settings"
|
138
154
|
)
|
139
155
|
end
|
140
156
|
|
141
157
|
def validate_workers
|
142
158
|
return if defined?(::ActiveJob)
|
143
159
|
|
144
|
-
all_queues = Shoryuken.
|
160
|
+
all_queues = Shoryuken.ungrouped_queues
|
145
161
|
queues_with_workers = Shoryuken.worker_registry.queues
|
146
162
|
|
147
163
|
(all_queues - queues_with_workers).each do |queue|
|
data/lib/shoryuken/fetcher.rb
CHANGED
@@ -4,23 +4,23 @@ module Shoryuken
|
|
4
4
|
|
5
5
|
FETCH_LIMIT = 10
|
6
6
|
|
7
|
-
|
7
|
+
attr_reader :group
|
8
|
+
|
9
|
+
def initialize(group)
|
10
|
+
@group = group
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(queue, limit)
|
8
14
|
started_at = Time.now
|
9
15
|
|
10
16
|
logger.debug { "Looking for new messages in #{queue}" }
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
sqs_msgs
|
19
|
-
rescue => ex
|
20
|
-
logger.error { "Error fetching message: #{ex.message}" }
|
21
|
-
logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
|
22
|
-
[]
|
23
|
-
end
|
18
|
+
sqs_msgs = Array(receive_messages(queue, [FETCH_LIMIT, limit].min))
|
19
|
+
|
20
|
+
logger.info { "Found #{sqs_msgs.size} messages for #{queue.name}" } unless sqs_msgs.empty?
|
21
|
+
logger.debug { "Fetcher for #{queue} completed in #{elapsed(started_at)} ms" }
|
22
|
+
|
23
|
+
sqs_msgs
|
24
24
|
end
|
25
25
|
|
26
26
|
private
|
@@ -29,10 +29,11 @@ module Shoryuken
|
|
29
29
|
# AWS limits the batch size by 10
|
30
30
|
limit = limit > FETCH_LIMIT ? FETCH_LIMIT : limit
|
31
31
|
|
32
|
-
options = Shoryuken.sqs_client_receive_message_opts.to_h.dup
|
33
|
-
|
32
|
+
options = Shoryuken.sqs_client_receive_message_opts[group].to_h.dup
|
33
|
+
|
34
|
+
options[:max_number_of_messages] = limit
|
34
35
|
options[:message_attribute_names] = %w(All)
|
35
|
-
options[:attribute_names]
|
36
|
+
options[:attribute_names] = %w(All)
|
36
37
|
|
37
38
|
options.merge!(queue.options)
|
38
39
|
|
data/lib/shoryuken/launcher.rb
CHANGED
@@ -3,17 +3,96 @@ module Shoryuken
|
|
3
3
|
include Util
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@
|
7
|
-
|
6
|
+
@managers = create_managers
|
7
|
+
@shutdowning = Concurrent::AtomicBoolean.new(false)
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
10
|
+
def start
|
11
|
+
logger.info { 'Starting' }
|
12
|
+
|
13
|
+
start_callback
|
14
|
+
start_managers
|
15
|
+
end
|
16
|
+
|
17
|
+
def stop!
|
18
|
+
initiate_stop
|
19
|
+
|
20
|
+
executor.shutdown
|
21
|
+
|
22
|
+
return if executor.wait_for_termination(Shoryuken.options[:timeout])
|
23
|
+
|
24
|
+
executor.kill
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
fire_event(:quiet, true)
|
29
|
+
|
30
|
+
initiate_stop
|
31
|
+
|
32
|
+
executor.shutdown
|
33
|
+
executor.wait_for_termination
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def executor
|
39
|
+
Concurrent.global_io_executor
|
40
|
+
end
|
41
|
+
|
42
|
+
def start_managers
|
43
|
+
@managers.each do |manager|
|
44
|
+
Concurrent::Promise.execute { manager.start }.rescue do |ex|
|
45
|
+
log_manager_failure(ex)
|
46
|
+
start_soft_shutdown
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def start_soft_shutdown
|
52
|
+
Process.kill('USR1', Process.pid) if @shutdowning.make_true
|
53
|
+
end
|
54
|
+
|
55
|
+
def log_manager_failure(ex)
|
56
|
+
return unless ex
|
57
|
+
|
58
|
+
logger.error { "Manager failed: #{ex.message}" }
|
59
|
+
logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
|
60
|
+
end
|
61
|
+
|
62
|
+
def initiate_stop
|
63
|
+
logger.info { 'Shutting down' }
|
64
|
+
|
65
|
+
@managers.each(&:stop)
|
66
|
+
|
67
|
+
stop_callback
|
68
|
+
end
|
69
|
+
|
70
|
+
def start_callback
|
71
|
+
if (callback = Shoryuken.start_callback)
|
72
|
+
logger.debug { 'Calling start_callback' }
|
73
|
+
callback.call
|
74
|
+
end
|
75
|
+
|
76
|
+
fire_event(:startup)
|
77
|
+
end
|
78
|
+
|
79
|
+
def stop_callback
|
80
|
+
if (callback = Shoryuken.stop_callback)
|
81
|
+
logger.debug { 'Calling stop_callback' }
|
82
|
+
callback.call
|
83
|
+
end
|
84
|
+
|
85
|
+
fire_event(:shutdown, true)
|
13
86
|
end
|
14
87
|
|
15
|
-
def
|
16
|
-
|
88
|
+
def create_managers
|
89
|
+
Shoryuken.groups.map do |group, options|
|
90
|
+
Shoryuken::Manager.new(
|
91
|
+
Shoryuken::Fetcher.new(group),
|
92
|
+
Shoryuken.polling_strategy(group).new(options[:queues]),
|
93
|
+
options[:concurrency]
|
94
|
+
)
|
95
|
+
end
|
17
96
|
end
|
18
97
|
end
|
19
98
|
end
|
data/lib/shoryuken/manager.rb
CHANGED
@@ -6,95 +6,71 @@ module Shoryuken
|
|
6
6
|
# See https://github.com/phstc/shoryuken/issues/348#issuecomment-292847028
|
7
7
|
MIN_DISPATCH_INTERVAL = 0.1
|
8
8
|
|
9
|
-
def initialize(fetcher, polling_strategy)
|
10
|
-
@
|
11
|
-
|
12
|
-
raise(ArgumentError, "Concurrency value #{@count} is invalid, it needs to be a positive number") unless @count > 0
|
13
|
-
|
14
|
-
@queues = Shoryuken.queues.dup.uniq
|
15
|
-
|
16
|
-
@done = Concurrent::AtomicBoolean.new(false)
|
17
|
-
|
18
|
-
@fetcher = fetcher
|
9
|
+
def initialize(fetcher, polling_strategy, concurrency)
|
10
|
+
@fetcher = fetcher
|
19
11
|
@polling_strategy = polling_strategy
|
20
|
-
|
21
|
-
@
|
22
|
-
@
|
12
|
+
@max_processors = concurrency
|
13
|
+
@busy_processors = Concurrent::AtomicFixnum.new(0)
|
14
|
+
@done = Concurrent::AtomicBoolean.new(false)
|
23
15
|
end
|
24
16
|
|
25
17
|
def start
|
26
|
-
|
27
|
-
|
28
|
-
dispatch_async
|
18
|
+
dispatch
|
29
19
|
end
|
30
20
|
|
31
|
-
def stop
|
21
|
+
def stop
|
32
22
|
@done.make_true
|
33
|
-
|
34
|
-
if (callback = Shoryuken.stop_callback)
|
35
|
-
logger.info { 'Calling on_stop callback' }
|
36
|
-
callback.call
|
37
|
-
end
|
38
|
-
|
39
|
-
fire_event(:shutdown, true)
|
40
|
-
|
41
|
-
logger.info { 'Shutting down workers' }
|
42
|
-
|
43
|
-
@dispatcher_executor.kill
|
44
|
-
|
45
|
-
if options[:shutdown]
|
46
|
-
hard_shutdown_in(options[:timeout])
|
47
|
-
else
|
48
|
-
soft_shutdown
|
49
|
-
end
|
50
23
|
end
|
51
24
|
|
52
|
-
|
53
|
-
logger.error { "Processor failed: #{ex.message}" }
|
54
|
-
logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
|
55
|
-
end
|
25
|
+
private
|
56
26
|
|
57
|
-
def
|
58
|
-
|
27
|
+
def stopped?
|
28
|
+
@done.true? || !Concurrent.global_io_executor.running?
|
59
29
|
end
|
60
30
|
|
61
|
-
|
31
|
+
def dispatch
|
32
|
+
return if stopped?
|
62
33
|
|
63
|
-
|
64
|
-
|
65
|
-
|
34
|
+
if !ready.positive? || (queue = @polling_strategy.next_queue).nil?
|
35
|
+
return dispatch_later
|
36
|
+
end
|
66
37
|
|
67
|
-
|
68
|
-
return if @done.true?
|
38
|
+
fire_event(:dispatch)
|
69
39
|
|
70
|
-
|
71
|
-
if ready.zero? || (queue = @polling_strategy.next_queue).nil?
|
72
|
-
sleep MIN_DISPATCH_INTERVAL
|
73
|
-
return
|
74
|
-
end
|
40
|
+
logger.info { "Ready: #{ready}, Busy: #{busy}, Active Queues: #{@polling_strategy.active_queues}" }
|
75
41
|
|
76
|
-
|
42
|
+
batched_queue?(queue) ? dispatch_batch(queue) : dispatch_single_messages(queue)
|
77
43
|
|
78
|
-
|
44
|
+
dispatch
|
45
|
+
end
|
79
46
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
47
|
+
def dispatch_later
|
48
|
+
sleep(MIN_DISPATCH_INTERVAL)
|
49
|
+
dispatch
|
84
50
|
end
|
85
51
|
|
86
52
|
def busy
|
87
|
-
@
|
53
|
+
@busy_processors.value
|
88
54
|
end
|
89
55
|
|
90
56
|
def ready
|
91
|
-
@
|
57
|
+
@max_processors - busy
|
92
58
|
end
|
93
59
|
|
94
|
-
def
|
60
|
+
def processor_done
|
61
|
+
@busy_processors.decrement
|
62
|
+
end
|
63
|
+
|
64
|
+
def assign(queue_name, sqs_msg)
|
65
|
+
return if stopped?
|
66
|
+
|
95
67
|
logger.debug { "Assigning #{sqs_msg.message_id}" }
|
96
68
|
|
97
|
-
@
|
69
|
+
@busy_processors.increment
|
70
|
+
|
71
|
+
Concurrent::Promise.execute {
|
72
|
+
Processor.new(queue_name, sqs_msg).process
|
73
|
+
}.then { processor_done }.rescue { processor_done }
|
98
74
|
end
|
99
75
|
|
100
76
|
def dispatch_batch(queue)
|
@@ -105,6 +81,7 @@ module Shoryuken
|
|
105
81
|
|
106
82
|
def dispatch_single_messages(queue)
|
107
83
|
messages = @fetcher.fetch(queue, ready)
|
84
|
+
|
108
85
|
@polling_strategy.messages_found(queue.name, messages.size)
|
109
86
|
messages.each { |message| assign(queue.name, message) }
|
110
87
|
end
|
@@ -113,24 +90,6 @@ module Shoryuken
|
|
113
90
|
Shoryuken.worker_registry.batch_receive_messages?(queue.name)
|
114
91
|
end
|
115
92
|
|
116
|
-
def soft_shutdown
|
117
|
-
@pool.shutdown
|
118
|
-
@pool.wait_for_termination
|
119
|
-
end
|
120
|
-
|
121
|
-
def hard_shutdown_in(delay)
|
122
|
-
if busy > 0
|
123
|
-
logger.info { "Pausing up to #{delay} seconds to allow workers to finish..." }
|
124
|
-
end
|
125
|
-
|
126
|
-
@pool.shutdown
|
127
|
-
|
128
|
-
return if @pool.wait_for_termination(delay)
|
129
|
-
|
130
|
-
logger.info { "Hard shutting down #{busy} busy workers" }
|
131
|
-
@pool.kill
|
132
|
-
end
|
133
|
-
|
134
93
|
def patch_batch!(sqs_msgs)
|
135
94
|
sqs_msgs.instance_eval do
|
136
95
|
def message_id
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module Shoryuken
|
2
|
+
class Options
|
3
|
+
DEFAULTS = {
|
4
|
+
concurrency: 25,
|
5
|
+
queues: [],
|
6
|
+
aws: {},
|
7
|
+
delay: 0,
|
8
|
+
timeout: 8,
|
9
|
+
lifecycle_events: {
|
10
|
+
startup: [],
|
11
|
+
dispatch: [],
|
12
|
+
quiet: [],
|
13
|
+
shutdown: []
|
14
|
+
}
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
@@groups = {}
|
18
|
+
@@worker_registry = DefaultWorkerRegistry.new
|
19
|
+
@@active_job_queue_name_prefixing = false
|
20
|
+
@@sqs_client = nil
|
21
|
+
@@sqs_client_receive_message_opts = {}
|
22
|
+
@@start_callback = nil
|
23
|
+
@@stop_callback = nil
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def add_group(group, concurrency)
|
27
|
+
groups[group] ||= {
|
28
|
+
concurrency: concurrency,
|
29
|
+
queues: []
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def groups
|
34
|
+
@@groups
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_queue(queue, weight, group)
|
38
|
+
weight.times do
|
39
|
+
groups[group][:queues] << queue
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def ungrouped_queues
|
44
|
+
groups.values.flat_map { |options| options[:queues] }
|
45
|
+
end
|
46
|
+
|
47
|
+
def worker_registry
|
48
|
+
@@worker_registry
|
49
|
+
end
|
50
|
+
|
51
|
+
def worker_registry=(worker_registry)
|
52
|
+
@@worker_registry = worker_registry
|
53
|
+
end
|
54
|
+
|
55
|
+
def polling_strategy(group)
|
56
|
+
options[group].to_h.fetch(:polling_strategy, Polling::WeightedRoundRobin)
|
57
|
+
end
|
58
|
+
|
59
|
+
def start_callback
|
60
|
+
@@start_callback
|
61
|
+
end
|
62
|
+
|
63
|
+
def start_callback=(start_callback)
|
64
|
+
@@start_callback = start_callback
|
65
|
+
end
|
66
|
+
|
67
|
+
def stop_callback
|
68
|
+
@@stop_callback
|
69
|
+
end
|
70
|
+
|
71
|
+
def stop_callback=(stop_callback)
|
72
|
+
@@stop_callback = stop_callback
|
73
|
+
end
|
74
|
+
|
75
|
+
def active_job_queue_name_prefixing
|
76
|
+
@@active_job_queue_name_prefixing
|
77
|
+
end
|
78
|
+
|
79
|
+
def active_job_queue_name_prefixing=(active_job_queue_name_prefixing)
|
80
|
+
@@active_job_queue_name_prefixing = active_job_queue_name_prefixing
|
81
|
+
end
|
82
|
+
|
83
|
+
def sqs_client
|
84
|
+
@@sqs_client ||= Aws::SQS::Client.new
|
85
|
+
end
|
86
|
+
|
87
|
+
def sqs_client=(sqs_client)
|
88
|
+
@@sqs_client = sqs_client
|
89
|
+
end
|
90
|
+
|
91
|
+
def sqs_client_receive_message_opts
|
92
|
+
@@sqs_client_receive_message_opts
|
93
|
+
end
|
94
|
+
|
95
|
+
def sqs_client_receive_message_opts=(sqs_client_receive_message_opts)
|
96
|
+
@@sqs_client_receive_message_opts['default'] = sqs_client_receive_message_opts
|
97
|
+
end
|
98
|
+
|
99
|
+
def options
|
100
|
+
@@options ||= DEFAULTS.dup
|
101
|
+
end
|
102
|
+
|
103
|
+
def logger
|
104
|
+
Shoryuken::Logging.logger
|
105
|
+
end
|
106
|
+
|
107
|
+
def register_worker(*args)
|
108
|
+
@@worker_registry.register_worker(*args)
|
109
|
+
end
|
110
|
+
|
111
|
+
def configure_server
|
112
|
+
yield self if server?
|
113
|
+
end
|
114
|
+
|
115
|
+
def server_middleware
|
116
|
+
@@server_chain ||= default_server_middleware
|
117
|
+
yield @@server_chain if block_given?
|
118
|
+
@@server_chain
|
119
|
+
end
|
120
|
+
|
121
|
+
def configure_client
|
122
|
+
yield self unless server?
|
123
|
+
end
|
124
|
+
|
125
|
+
def client_middleware
|
126
|
+
@@client_chain ||= default_client_middleware
|
127
|
+
yield @@client_chain if block_given?
|
128
|
+
@@client_chain
|
129
|
+
end
|
130
|
+
|
131
|
+
def default_worker_options
|
132
|
+
@@default_worker_options ||= {
|
133
|
+
'queue' => 'default',
|
134
|
+
'delete' => false,
|
135
|
+
'auto_delete' => false,
|
136
|
+
'auto_visibility_timeout' => false,
|
137
|
+
'retry_intervals' => nil,
|
138
|
+
'batch' => false
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
def default_worker_options=(default_worker_options)
|
143
|
+
@@default_worker_options = default_worker_options
|
144
|
+
end
|
145
|
+
|
146
|
+
def on_start(&block)
|
147
|
+
@@start_callback = block
|
148
|
+
end
|
149
|
+
|
150
|
+
def on_stop(&block)
|
151
|
+
@@stop_callback = block
|
152
|
+
end
|
153
|
+
|
154
|
+
# Register a block to run at a point in the Shoryuken lifecycle.
|
155
|
+
# :startup, :quiet or :shutdown are valid events.
|
156
|
+
#
|
157
|
+
# Shoryuken.configure_server do |config|
|
158
|
+
# config.on(:shutdown) do
|
159
|
+
# puts "Goodbye cruel world!"
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
def on(event, &block)
|
163
|
+
fail ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
164
|
+
fail ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
165
|
+
options[:lifecycle_events][event] << block
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def default_server_middleware
|
171
|
+
Middleware::Chain.new do |m|
|
172
|
+
m.add Middleware::Server::Timing
|
173
|
+
m.add Middleware::Server::ExponentialBackoffRetry
|
174
|
+
m.add Middleware::Server::AutoDelete
|
175
|
+
m.add Middleware::Server::AutoExtendVisibility
|
176
|
+
if defined?(::ActiveRecord::Base)
|
177
|
+
require 'shoryuken/middleware/server/active_record'
|
178
|
+
m.add Middleware::Server::ActiveRecord
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def default_client_middleware
|
184
|
+
Middleware::Chain.new
|
185
|
+
end
|
186
|
+
|
187
|
+
def server?
|
188
|
+
defined?(Shoryuken::CLI)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|