fastly_nsq 0.13.2 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.env +4 -0
- data/.overcommit.yml +3 -3
- data/.rubocop.yml +11 -1
- data/.travis.yml +8 -1
- data/Gemfile +9 -0
- data/README.md +52 -82
- data/Rakefile +2 -0
- data/bin/fastly_nsq +1 -0
- data/docker-compose.yml +23 -0
- data/examples/.sample.env +0 -3
- data/fastly_nsq.gemspec +7 -8
- data/lib/fastly_nsq.rb +44 -50
- data/lib/fastly_nsq/cli.rb +20 -14
- data/lib/fastly_nsq/consumer.rb +26 -30
- data/lib/fastly_nsq/feeder.rb +16 -0
- data/lib/fastly_nsq/http/nsqd.rb +7 -1
- data/lib/fastly_nsq/http/nsqlookupd.rb +1 -1
- data/lib/fastly_nsq/launcher.rb +31 -23
- data/lib/fastly_nsq/listener.rb +34 -103
- data/lib/fastly_nsq/manager.rb +48 -72
- data/lib/fastly_nsq/message.rb +2 -0
- data/lib/fastly_nsq/messenger.rb +5 -5
- data/lib/fastly_nsq/priority_queue.rb +12 -0
- data/lib/fastly_nsq/priority_thread_pool.rb +32 -0
- data/lib/fastly_nsq/producer.rb +52 -32
- data/lib/fastly_nsq/testing.rb +239 -0
- data/lib/fastly_nsq/tls_options.rb +2 -0
- data/lib/fastly_nsq/version.rb +3 -1
- data/spec/{lib/fastly_nsq/cli_spec.rb → cli_spec.rb} +2 -0
- data/spec/consumer_spec.rb +59 -0
- data/spec/fastly_nsq_spec.rb +72 -0
- data/spec/feeder_spec.rb +22 -0
- data/spec/{lib/fastly_nsq/http → http}/nsqd_spec.rb +1 -1
- data/spec/{lib/fastly_nsq/http → http}/nsqlookupd_spec.rb +1 -1
- data/spec/{lib/fastly_nsq/http_spec.rb → http_spec.rb} +3 -1
- data/spec/integration_spec.rb +48 -0
- data/spec/launcher_spec.rb +50 -0
- data/spec/listener_spec.rb +184 -0
- data/spec/manager_spec.rb +111 -0
- data/spec/matchers/delegate.rb +32 -0
- data/spec/{lib/fastly_nsq/message_spec.rb → message_spec.rb} +2 -0
- data/spec/{lib/fastly_nsq/messenger_spec.rb → messenger_spec.rb} +7 -5
- data/spec/priority_thread_pool_spec.rb +19 -0
- data/spec/producer_spec.rb +94 -0
- data/spec/spec_helper.rb +32 -28
- data/spec/support/http.rb +37 -0
- data/spec/support/webmock.rb +22 -0
- data/spec/{lib/fastly_nsq/tls_options_spec.rb → tls_options_spec.rb} +2 -0
- metadata +54 -96
- data/env_configuration_for_local_gem_tests.yml +0 -5
- data/example_config_class.rb +0 -20
- data/examples/Rakefile +0 -41
- data/lib/fastly_nsq/fake_backend.rb +0 -114
- data/lib/fastly_nsq/listener/config.rb +0 -35
- data/lib/fastly_nsq/rake_task.rb +0 -78
- data/lib/fastly_nsq/strategy.rb +0 -36
- data/spec/lib/fastly_nsq/consumer_spec.rb +0 -72
- data/spec/lib/fastly_nsq/fake_backend_spec.rb +0 -135
- data/spec/lib/fastly_nsq/fastly_nsq_spec.rb +0 -10
- data/spec/lib/fastly_nsq/launcher_spec.rb +0 -56
- data/spec/lib/fastly_nsq/listener_spec.rb +0 -213
- data/spec/lib/fastly_nsq/manager_spec.rb +0 -127
- data/spec/lib/fastly_nsq/producer_spec.rb +0 -60
- data/spec/lib/fastly_nsq/rake_task_spec.rb +0 -142
- data/spec/lib/fastly_nsq/strategy_spec.rb +0 -36
- data/spec/lib/fastly_nsq_spec.rb +0 -18
- data/spec/support/env_helpers.rb +0 -15
data/lib/fastly_nsq/cli.rb
CHANGED
@@ -25,19 +25,17 @@ class FastlyNsq::CLI
|
|
25
25
|
|
26
26
|
def run
|
27
27
|
startup
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
exit(0)
|
40
|
-
end
|
28
|
+
|
29
|
+
launcher.beat
|
30
|
+
|
31
|
+
read_loop
|
32
|
+
rescue Interrupt
|
33
|
+
FastlyNsq.logger.info 'Shutting down'
|
34
|
+
launcher.stop
|
35
|
+
# Explicitly exit so busy Processor threads can't block
|
36
|
+
# process shutdown.
|
37
|
+
FastlyNsq.logger.info 'Bye!'
|
38
|
+
exit(0)
|
41
39
|
end
|
42
40
|
|
43
41
|
private
|
@@ -75,6 +73,10 @@ class FastlyNsq::CLI
|
|
75
73
|
opts = {}
|
76
74
|
|
77
75
|
@parser = OptionParser.new do |o|
|
76
|
+
o.on '-c', '--concurrency COUNT', 'Number of threads used to process messages' do |arg|
|
77
|
+
opts[:max_threads] = arg
|
78
|
+
end
|
79
|
+
|
78
80
|
o.on '-d', '--daemon', 'Daemonize process' do |arg|
|
79
81
|
opts[:daemonize] = arg
|
80
82
|
end
|
@@ -178,7 +180,7 @@ class FastlyNsq::CLI
|
|
178
180
|
raise Interrupt
|
179
181
|
when 'USR1'
|
180
182
|
FastlyNsq.logger.info 'Received USR1, no longer accepting new work'
|
181
|
-
launcher.
|
183
|
+
launcher.stop_listeners
|
182
184
|
when 'TTIN'
|
183
185
|
handle_ttin
|
184
186
|
end
|
@@ -247,6 +249,10 @@ class FastlyNsq::CLI
|
|
247
249
|
options[:logfile]
|
248
250
|
end
|
249
251
|
|
252
|
+
def max_threads
|
253
|
+
options[:max_threads]
|
254
|
+
end
|
255
|
+
|
250
256
|
def pidfile
|
251
257
|
options[:pidfile]
|
252
258
|
end
|
data/lib/fastly_nsq/consumer.rb
CHANGED
@@ -1,43 +1,39 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
extend Forwardable
|
6
|
-
def_delegator :connection, :pop
|
7
|
-
def_delegator :connection, :pop_without_blocking
|
8
|
-
def_delegator :connection, :size
|
9
|
-
def_delegator :connection, :terminate
|
3
|
+
class FastlyNsq::Consumer
|
4
|
+
extend Forwardable
|
10
5
|
|
11
|
-
|
12
|
-
@topic = topic
|
13
|
-
@channel = channel
|
14
|
-
@tls_options = TlsOptions.as_hash(tls_options)
|
15
|
-
@connector = connector
|
16
|
-
connection
|
17
|
-
end
|
6
|
+
DEFAULT_CONNECTION_TIMEOUT = 5 # seconds
|
18
7
|
|
19
|
-
|
20
|
-
connection.size.zero?
|
21
|
-
end
|
8
|
+
attr_reader :channel, :topic, :connection, :connect_timeout
|
22
9
|
|
23
|
-
|
10
|
+
def_delegators :connection, :size, :terminate, :connected?, :pop, :pop_without_blocking
|
24
11
|
|
25
|
-
|
12
|
+
def initialize(topic:, channel:, queue: nil, tls_options: nil, connect_timeout: DEFAULT_CONNECTION_TIMEOUT)
|
13
|
+
@topic = topic
|
14
|
+
@channel = channel
|
15
|
+
@tls_options = FastlyNsq::TlsOptions.as_hash(tls_options)
|
16
|
+
@connect_timeout = connect_timeout
|
26
17
|
|
27
|
-
|
28
|
-
|
29
|
-
|
18
|
+
@connection = connect(queue)
|
19
|
+
end
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
size.zero?
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
30
26
|
|
31
|
-
|
32
|
-
@connector || FastlyNsq.strategy::Consumer
|
33
|
-
end
|
27
|
+
attr_reader :tls_options
|
34
28
|
|
35
|
-
|
29
|
+
def connect(queue)
|
30
|
+
Nsq::Consumer.new(
|
36
31
|
{
|
37
|
-
nsqlookupd:
|
32
|
+
nsqlookupd: FastlyNsq.lookupd_http_addresses,
|
38
33
|
topic: topic,
|
39
34
|
channel: channel,
|
40
|
-
|
41
|
-
|
35
|
+
queue: queue,
|
36
|
+
}.merge(tls_options),
|
37
|
+
)
|
42
38
|
end
|
43
39
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FastlyNsq::Feeder
|
4
|
+
attr_reader :processor, :priority
|
5
|
+
|
6
|
+
def initialize(processor, priority)
|
7
|
+
@processor = processor
|
8
|
+
@priority = priority
|
9
|
+
end
|
10
|
+
|
11
|
+
# @see http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadPoolExecutor.html#post-instance_method
|
12
|
+
# @see {Nsq::Connection#read_loop}
|
13
|
+
def push(message)
|
14
|
+
FastlyNsq.manager.pool.post(priority) { processor.call(message) }
|
15
|
+
end
|
16
|
+
end
|
data/lib/fastly_nsq/http/nsqd.rb
CHANGED
@@ -8,7 +8,13 @@ class FastlyNsq::Http
|
|
8
8
|
def_delegator :client, :get
|
9
9
|
def_delegator :client, :post
|
10
10
|
|
11
|
-
BASE_NSQD_URL = ENV.fetch
|
11
|
+
BASE_NSQD_URL = ENV.fetch('NSQD_URL') do
|
12
|
+
if ENV['NSQD_HTTPS_ADDRESS']
|
13
|
+
"https://#{ENV.fetch('NSQD_HTTPS_ADDRESS')}"
|
14
|
+
else
|
15
|
+
"http://#{ENV.fetch('NSQD_HTTP_ADDRESS')}"
|
16
|
+
end
|
17
|
+
end
|
12
18
|
VALID_FORMATS = %w[text json].freeze
|
13
19
|
|
14
20
|
##
|
@@ -7,7 +7,7 @@ class FastlyNsq::Http
|
|
7
7
|
extend Forwardable
|
8
8
|
def_delegator :client, :get
|
9
9
|
|
10
|
-
BASE_NSQLOOKUPD_URL = "http://#{ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS', '').split(',')[0]}"
|
10
|
+
BASE_NSQLOOKUPD_URL = "http://#{ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS', '').split(',')[0]}"
|
11
11
|
|
12
12
|
##
|
13
13
|
# List of producers for a given topic
|
data/lib/fastly_nsq/launcher.rb
CHANGED
@@ -5,29 +5,34 @@ require 'fastly_nsq/safe_thread'
|
|
5
5
|
class FastlyNsq::Launcher
|
6
6
|
include FastlyNsq::SafeThread
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
attr_reader :timeout, :logger
|
9
|
+
attr_accessor :pulse
|
10
|
+
|
11
|
+
def manager
|
12
|
+
FastlyNsq.manager
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
-
@
|
16
|
-
@
|
15
|
+
def initialize(timeout: 5, pulse: 5, logger: FastlyNsq.logger, **options)
|
16
|
+
@done = false
|
17
|
+
@timeout = timeout
|
18
|
+
@pulse = pulse
|
19
|
+
@logger = logger
|
20
|
+
|
21
|
+
FastlyNsq.manager = FastlyNsq::Manager.new(options)
|
17
22
|
end
|
18
23
|
|
19
|
-
def
|
20
|
-
@
|
21
|
-
@manager.quiet
|
24
|
+
def beat
|
25
|
+
@heartbeat ||= safe_thread('heartbeat', &method(:start_heartbeat))
|
22
26
|
end
|
23
27
|
|
24
|
-
# Shuts down the process. This method does not
|
25
|
-
# return until all work is complete and cleaned up.
|
26
|
-
# It can take up to the timeout to complete.
|
27
28
|
def stop
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
@done = true
|
30
|
+
manager.terminate(timeout)
|
31
|
+
end
|
32
|
+
|
33
|
+
def stop_listeners
|
34
|
+
@done = true
|
35
|
+
manager.stop_listeners
|
31
36
|
end
|
32
37
|
|
33
38
|
def stopping?
|
@@ -37,25 +42,28 @@ class FastlyNsq::Launcher
|
|
37
42
|
private
|
38
43
|
|
39
44
|
def heartbeat
|
40
|
-
|
45
|
+
logger.debug do
|
41
46
|
[
|
42
47
|
'HEARTBEAT:',
|
43
|
-
'
|
44
|
-
'
|
48
|
+
'busy:', manager.pool.length,
|
49
|
+
'processed:', manager.pool.completed_task_count,
|
50
|
+
'max_threads:', manager.pool.max_length,
|
51
|
+
'max_queue_size:', manager.pool.largest_length,
|
52
|
+
'listeners:', manager.listeners.count
|
45
53
|
].join(' ')
|
46
54
|
end
|
47
55
|
|
48
56
|
# TODO: Check the health of the system overall and kill it if needed
|
49
57
|
# ::Process.kill('dieing because...', $$)
|
50
58
|
rescue => e
|
51
|
-
|
59
|
+
logger.error "Heartbeat error: #{e.message}"
|
52
60
|
end
|
53
61
|
|
54
62
|
def start_heartbeat
|
55
|
-
|
63
|
+
until manager.stopped?
|
56
64
|
heartbeat
|
57
|
-
sleep
|
65
|
+
sleep pulse
|
58
66
|
end
|
59
|
-
|
67
|
+
logger.info('Heartbeat stopping...')
|
60
68
|
end
|
61
69
|
end
|
data/lib/fastly_nsq/listener.rb
CHANGED
@@ -1,117 +1,48 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require 'fastly_nsq/safe_thread'
|
6
|
-
require 'fastly_nsq/listener/config'
|
3
|
+
class FastlyNsq::Listener
|
4
|
+
extend Forwardable
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
include FastlyNsq::SafeThread
|
6
|
+
DEFAULT_PRIORITY = 0
|
7
|
+
DEFAULT_CONNECTION_TIMEOUT = 5 # seconds
|
11
8
|
|
12
|
-
|
13
|
-
new(*args).go
|
14
|
-
end
|
9
|
+
def_delegators :consumer, :connected?
|
15
10
|
|
16
|
-
|
17
|
-
@consumer = consumer || FastlyNsq::Consumer.new(topic: topic, channel: channel)
|
18
|
-
@done = false
|
19
|
-
@logger = options.fetch :logger, FastlyNsq.logger
|
20
|
-
@manager = options[:manager] || FastlyNsq::Manager.new
|
21
|
-
@preprocessor = options[:preprocessor]
|
22
|
-
@processor = processor
|
23
|
-
@thread = nil
|
24
|
-
@topic = topic
|
25
|
-
end
|
11
|
+
attr_reader :preprocessor, :topic, :processor, :priority, :channel, :logger, :consumer
|
26
12
|
|
27
|
-
|
28
|
-
|
29
|
-
consumer: @consumer,
|
30
|
-
manager: @manager,
|
31
|
-
preprocessor: @preprocessor,
|
32
|
-
processor: @processor,
|
33
|
-
topic: @topic,
|
34
|
-
}
|
35
|
-
end
|
13
|
+
def initialize(topic:, processor:, preprocessor: FastlyNsq.preprocessor, channel: FastlyNsq.channel, consumer: nil,
|
14
|
+
logger: FastlyNsq.logger, priority: DEFAULT_PRIORITY, connect_timeout: DEFAULT_CONNECTION_TIMEOUT)
|
36
15
|
|
37
|
-
|
38
|
-
|
39
|
-
dup
|
40
|
-
end
|
16
|
+
raise ArgumentError, "processor #{processor.inspect} does not respond to #call" unless processor.respond_to?(:call)
|
17
|
+
raise ArgumentError, "priority #{priority.inspect} must be a Integer" unless priority.is_a?(Integer)
|
41
18
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
19
|
+
@channel = channel
|
20
|
+
@logger = logger
|
21
|
+
@preprocessor = preprocessor
|
22
|
+
@processor = processor
|
23
|
+
@topic = topic
|
24
|
+
@priority = priority
|
46
25
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
preprocess message
|
52
|
-
@processor.process message
|
53
|
-
end
|
26
|
+
@consumer = consumer || FastlyNsq::Consumer.new(topic: topic,
|
27
|
+
connect_timeout: connect_timeout,
|
28
|
+
channel: channel,
|
29
|
+
queue: FastlyNsq::Feeder.new(self, priority))
|
54
30
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@manager.listener_stopped(self)
|
59
|
-
rescue FastlyNsq::Shutdown
|
60
|
-
@manager.listener_stopped(self)
|
61
|
-
rescue Exception => e # rubocop:disable Lint/RescueException
|
62
|
-
@logger.error e.inspect
|
63
|
-
@manager.listener_killed(self)
|
64
|
-
end
|
65
|
-
|
66
|
-
def status
|
67
|
-
@thread.status if @thread
|
68
|
-
end
|
69
|
-
|
70
|
-
def terminate
|
71
|
-
@done = true
|
72
|
-
cleanup
|
73
|
-
return unless @thread
|
74
|
-
@logger.info "< Listener TERM: topic #{@topic}"
|
75
|
-
# Interrupt a Consumer blocking in pop with no messages otherwise it will never shutdown
|
76
|
-
@thread.raise FastlyNsq::Shutdown if @consumer.empty?
|
77
|
-
end
|
78
|
-
|
79
|
-
def kill
|
80
|
-
@done = true
|
81
|
-
cleanup
|
82
|
-
return unless @thread
|
83
|
-
@logger.info "< Listener KILL: topic #{@topic}"
|
84
|
-
@thread.raise FastlyNsq::Shutdown
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def log(message)
|
90
|
-
@logger.info "[NSQ] Message received on topic [#{@topic}]: #{message}" if @logger
|
91
|
-
end
|
92
|
-
|
93
|
-
def cleanup
|
94
|
-
@consumer.terminate
|
95
|
-
@logger.info "< Consumer terminated: topic [#{@topic}]"
|
96
|
-
end
|
97
|
-
|
98
|
-
def next_message
|
99
|
-
nsq_message = @consumer.pop # TODO: consumer.pop do |message|
|
100
|
-
message = FastlyNsq::Message.new(nsq_message)
|
101
|
-
result = yield message
|
102
|
-
message.finish if result
|
103
|
-
end
|
31
|
+
FastlyNsq.manager.add_listener(self)
|
32
|
+
end
|
104
33
|
|
105
|
-
|
106
|
-
|
107
|
-
|
34
|
+
def call(nsq_message)
|
35
|
+
message = FastlyNsq::Message.new(nsq_message)
|
36
|
+
logger.info "[NSQ] Message received on topic [#{topic}]: #{message}"
|
37
|
+
preprocessor&.call(message)
|
38
|
+
result = processor.call(message)
|
39
|
+
message.finish if result
|
40
|
+
message
|
41
|
+
end
|
108
42
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
end
|
43
|
+
def terminate
|
44
|
+
return unless connected?
|
45
|
+
consumer.terminate
|
46
|
+
logger.info "< Consumer terminated: topic [#{topic}]"
|
114
47
|
end
|
115
48
|
end
|
116
|
-
|
117
|
-
class FastlyNsq::Shutdown < StandardError; end
|
data/lib/fastly_nsq/manager.rb
CHANGED
@@ -1,104 +1,80 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'set'
|
4
|
-
|
5
3
|
class FastlyNsq::Manager
|
6
|
-
|
4
|
+
DEADLINE = 30
|
5
|
+
DEFAULT_POOL_SIZE = 5
|
6
|
+
|
7
|
+
attr_reader :done, :pool, :logger
|
7
8
|
|
8
|
-
def initialize(
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
|
9
|
+
def initialize(logger: FastlyNsq.logger, **pool_options)
|
10
|
+
@done = false
|
11
|
+
@logger = logger
|
12
|
+
@pool = FastlyNsq::PriorityThreadPool.new(
|
13
|
+
{ fallback_policy: :caller_runs, max_threads: DEFAULT_POOL_SIZE }.merge(pool_options),
|
14
|
+
)
|
13
15
|
end
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
@listeners.each(&:start)
|
17
|
+
def topic_listeners
|
18
|
+
@topic_listeners ||= {}
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
21
|
+
def topics
|
22
|
+
topic_listeners.keys
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
25
|
+
def listeners
|
26
|
+
topic_listeners.values.to_set
|
26
27
|
end
|
27
28
|
|
28
|
-
|
29
|
+
def terminate(deadline = DEADLINE)
|
30
|
+
return if done
|
29
31
|
|
30
|
-
|
31
|
-
quiet
|
32
|
+
stop_listeners
|
32
33
|
|
33
|
-
|
34
|
-
return if @listeners.empty?
|
34
|
+
return if pool.shutdown?
|
35
35
|
|
36
|
-
|
37
|
-
remaining = deadline - Time.now
|
38
|
-
while remaining > PAUSE_TIME
|
39
|
-
return if @listeners.empty?
|
40
|
-
sleep PAUSE_TIME
|
41
|
-
remaining = deadline - Time.now
|
42
|
-
end
|
43
|
-
return if @listeners.empty?
|
36
|
+
stop_processing(deadline)
|
44
37
|
|
45
|
-
|
38
|
+
@done = true
|
46
39
|
end
|
47
40
|
|
48
41
|
def stopped?
|
49
|
-
|
42
|
+
done
|
50
43
|
end
|
51
44
|
|
52
|
-
def
|
53
|
-
|
54
|
-
@listeners.delete listener
|
55
|
-
end
|
56
|
-
end
|
45
|
+
def add_listener(listener)
|
46
|
+
logger.info { "Listening to topic:'#{listener.topic}' on channel: '#{listener.channel}'" }
|
57
47
|
|
58
|
-
|
59
|
-
|
60
|
-
@listeners.delete listener
|
61
|
-
unless @done
|
62
|
-
FastlyNsq.logger.info { "recreating listener for: #{listener.identity}" }
|
63
|
-
new_listener = listener.reset_then_dup
|
64
|
-
@listeners << new_listener
|
65
|
-
new_listener.start
|
66
|
-
end
|
48
|
+
if topic_listeners[listener.topic]
|
49
|
+
logger.warn { "topic: #{listener.topic} was added more than once" }
|
67
50
|
end
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
51
|
|
72
|
-
|
73
|
-
|
74
|
-
FastlyNsq.logger.debug { "starting listeners: #{FastlyNsq.topic_map.inspect}" }
|
52
|
+
topic_listeners[listener.topic] = listener
|
53
|
+
end
|
75
54
|
|
76
|
-
|
77
|
-
|
78
|
-
|
55
|
+
def transfer(new_manager, deadline: DEADLINE)
|
56
|
+
new_manager.topic_listeners.merge!(topic_listeners)
|
57
|
+
stop_processing(deadline)
|
58
|
+
topic_listeners.clear
|
59
|
+
@done = true
|
79
60
|
end
|
80
61
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
channel: FastlyNsq.channel,
|
86
|
-
processor: processor,
|
87
|
-
preprocessor: FastlyNsq.preprocessor,
|
88
|
-
manager: self,
|
89
|
-
)
|
62
|
+
def stop_listeners
|
63
|
+
logger.info { 'Stopping listeners' }
|
64
|
+
listeners.each(&:terminate)
|
65
|
+
topic_listeners.clear
|
90
66
|
end
|
91
67
|
|
92
|
-
|
93
|
-
cleanup = nil
|
94
|
-
@plock.synchronize do
|
95
|
-
cleanup = @listeners.dup
|
96
|
-
end
|
68
|
+
protected
|
97
69
|
|
98
|
-
|
99
|
-
|
100
|
-
|
70
|
+
def stop_processing(deadline)
|
71
|
+
logger.info { 'Stopping processors' }
|
72
|
+
pool.shutdown
|
73
|
+
|
74
|
+
logger.info { 'Waiting for processors to finish...' }
|
75
|
+
return if pool.wait_for_termination(deadline)
|
101
76
|
|
102
|
-
|
77
|
+
logger.info { 'Killing processors...' }
|
78
|
+
pool.kill
|
103
79
|
end
|
104
80
|
end
|