fastly_nsq 0.13.2 → 1.0.2
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 +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
|