shoryuken 3.0.11 → 3.1.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/.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
|