fastly_nsq 0.6.0 → 0.7.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/.github/PULL_REQUEST_TEMPLATE.md +6 -3
- data/.travis.yml +1 -1
- data/README.md +23 -73
- data/env_configuration_for_local_gem_tests.yml +0 -1
- data/examples/.sample.env +0 -2
- data/examples/Rakefile +20 -67
- data/lib/fastly_nsq/{message_queue/consumer.rb → consumer.rb} +8 -8
- data/lib/fastly_nsq/fake_backend.rb +100 -0
- data/lib/fastly_nsq/listener.rb +59 -0
- data/lib/fastly_nsq/message.rb +18 -0
- data/lib/fastly_nsq/{message_queue/producer.rb → producer.rb} +8 -8
- data/lib/fastly_nsq/rake_task.rb +39 -43
- data/lib/fastly_nsq/ssl_context.rb +35 -33
- data/lib/fastly_nsq/strategy.rb +38 -0
- data/lib/fastly_nsq/version.rb +1 -1
- data/lib/fastly_nsq.rb +21 -1
- data/spec/lib/fastly_nsq/consumer_spec.rb +68 -0
- data/spec/lib/fastly_nsq/{fake_message_queue_spec.rb → fake_backend_spec.rb} +23 -23
- data/spec/lib/fastly_nsq/listener_spec.rb +116 -0
- data/spec/lib/fastly_nsq/message_spec.rb +24 -0
- data/spec/lib/fastly_nsq/producer_spec.rb +56 -0
- data/spec/lib/fastly_nsq/rake_task_spec.rb +87 -74
- data/spec/lib/fastly_nsq/ssl_context_spec.rb +6 -6
- data/spec/lib/fastly_nsq/{message_queue/strategy_spec.rb → strategy_spec.rb} +6 -5
- data/spec/lib/fastly_nsq_spec.rb +18 -0
- data/spec/spec_helper.rb +1 -6
- metadata +15 -16
- data/lib/fastly_nsq/fake_message_queue.rb +0 -98
- data/lib/fastly_nsq/message_queue/listener.rb +0 -49
- data/lib/fastly_nsq/message_queue/strategy.rb +0 -34
- data/lib/fastly_nsq/message_queue.rb +0 -21
- data/lib/fastly_nsq/sample_message_processor.rb +0 -50
- data/spec/lib/fastly_nsq/message_queue/consumer_spec.rb +0 -60
- data/spec/lib/fastly_nsq/message_queue/listener_spec.rb +0 -90
- data/spec/lib/fastly_nsq/message_queue/producer_spec.rb +0 -49
- data/spec/lib/fastly_nsq/message_queue_spec.rb +0 -32
- data/spec/lib/fastly_nsq/sample_message_processor_spec.rb +0 -38
data/lib/fastly_nsq/rake_task.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/tasklib'
|
3
3
|
|
4
|
-
module
|
4
|
+
module FastlyNsq
|
5
5
|
class RakeTask < Rake::TaskLib
|
6
|
-
attr_accessor :name, :channel
|
6
|
+
attr_accessor :name, :channel, :topics, :preprocessor
|
7
|
+
attr_writer :listener, :logger
|
7
8
|
|
8
9
|
def initialize(*args, &task_block)
|
9
10
|
@name = args.shift || :begin_listening
|
@@ -15,68 +16,63 @@ module MessageQueue
|
|
15
16
|
yield(*[self, task_args].slice(0, task_block.arity))
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
guard_missing_channel
|
23
|
-
run_tasks
|
19
|
+
initialize_values task_args
|
20
|
+
listen_to_configured_topics
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
27
24
|
|
28
25
|
private
|
29
26
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
27
|
+
def listen_to_configured_topics
|
28
|
+
topic_per_thread do |topic, processor|
|
29
|
+
logger.info "Listening to queue, topic:'#{topic}' and channel: '#{channel}'"
|
30
|
+
listener.listen_to topic: topic,
|
31
|
+
channel: channel,
|
32
|
+
logger: logger,
|
33
|
+
processor: processor,
|
34
|
+
preprocessor: preprocessor
|
35
|
+
logger.info "... done listening on topic:'#{topic}' and channel: '#{channel}'."
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
36
|
-
def
|
37
|
-
|
38
|
-
Thread.new do
|
39
|
-
wrap_helpful_output(topic) do
|
40
|
-
MessageQueue::Listener.new(topic: topic, channel: channel).go
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
non_main_threads.map(&:join)
|
39
|
+
def require_arg(arg, arg_list)
|
40
|
+
arg_list.fetch(arg) { raise ArgumentError, "required configuration '#{arg}' is missing." }
|
46
41
|
end
|
47
42
|
|
48
|
-
def
|
49
|
-
|
43
|
+
def add_rake_task_description_if_one_needed
|
44
|
+
unless ::Rake.application.last_description
|
45
|
+
desc 'Listen to NSQ on topic using channel'
|
46
|
+
end
|
50
47
|
end
|
51
48
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
49
|
+
def topic_per_thread
|
50
|
+
listener_threads = []
|
51
|
+
topics.each do |(topic, processor)|
|
52
|
+
thread = Thread.new do
|
53
|
+
yield topic, processor
|
54
|
+
end
|
55
|
+
thread.abort_on_exception = true
|
56
|
+
listener_threads << thread
|
55
57
|
end
|
56
|
-
end
|
57
58
|
|
58
|
-
|
59
|
-
output "Listening to queue, topic:'#{topic}' and channel: '#{channel}'"
|
60
|
-
yield
|
61
|
-
output "... done listening on topic:'#{topic}' and channel: '#{channel}'."
|
59
|
+
listener_threads.map(&:join)
|
62
60
|
end
|
63
61
|
|
64
|
-
def
|
65
|
-
|
66
|
-
rescue NoMethodError => exception
|
67
|
-
if exception.message =~ /undefined method `topics'/
|
68
|
-
raise ArgumentError, 'MessageProcessor.topics is not defined.'
|
69
|
-
else
|
70
|
-
raise exception
|
71
|
-
end
|
62
|
+
def listener
|
63
|
+
@listener || FastlyNsq::Listener
|
72
64
|
end
|
73
65
|
|
74
|
-
def
|
75
|
-
logger.
|
66
|
+
def logger
|
67
|
+
@logger || FastlyNsq.logger || Logger.new(STDOUT)
|
76
68
|
end
|
77
69
|
|
78
|
-
def
|
79
|
-
|
70
|
+
def initialize_values(task_args)
|
71
|
+
@channel ||= require_arg :channel, task_args
|
72
|
+
@topics ||= require_arg :topics, task_args
|
73
|
+
@listener ||= task_args[:listener]
|
74
|
+
@logger ||= task_args[:logger]
|
75
|
+
@preprocessor ||= task_args[:preprocessor]
|
80
76
|
end
|
81
77
|
end
|
82
78
|
end
|
@@ -1,44 +1,46 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module FastlyNsq
|
2
|
+
class SSLContext
|
3
|
+
def initialize(context = nil)
|
4
|
+
@context = context || {}
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
def to_h
|
8
|
+
merge_contexts
|
9
|
+
if empty_context?
|
10
|
+
nil
|
11
|
+
else
|
12
|
+
@context
|
13
|
+
end
|
12
14
|
end
|
13
|
-
end
|
14
15
|
|
15
|
-
|
16
|
+
private
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def env_key
|
19
|
+
ENV.fetch('NSQ_SSL_KEY', nil)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def env_certificate
|
23
|
+
ENV.fetch('NSQ_SSL_CERTIFICATE', nil)
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def env_ca_certificate
|
27
|
+
ENV.fetch('NSQ_SSL_CA_CERTIFICATE', nil)
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
def env_default_hash
|
31
|
+
{
|
32
|
+
key: env_key,
|
33
|
+
certificate: env_certificate,
|
34
|
+
ca_certificate: env_ca_certificate,
|
35
|
+
}
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def merge_contexts
|
39
|
+
@context = env_default_hash.merge(@context)
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
def empty_context?
|
43
|
+
@context.all? { |_key, value| value.nil? }
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module FastlyNsq
|
2
|
+
module Strategy
|
3
|
+
class InvalidParameterError < StandardError; end
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def for_queue
|
8
|
+
real_queue || fake_queue || error
|
9
|
+
end
|
10
|
+
|
11
|
+
private_class_method
|
12
|
+
|
13
|
+
ERR_MESSAGE = "You must set ENV['FAKE_QUEUE'] to either true or false".freeze
|
14
|
+
|
15
|
+
def error
|
16
|
+
raise InvalidParameterError, ERR_MESSAGE
|
17
|
+
end
|
18
|
+
|
19
|
+
FALSY_VALUES = [false, 0, '0', 'false', 'FALSE', 'off', 'OFF', nil].freeze
|
20
|
+
TRUTHY_VALUES = [true, 1, '1', 'true', 'TRUE', 'on', 'ON'].freeze
|
21
|
+
|
22
|
+
def fake_queue
|
23
|
+
FastlyNsq::FakeBackend if should_use_fake_queue?
|
24
|
+
end
|
25
|
+
|
26
|
+
def should_use_real_queue?
|
27
|
+
FALSY_VALUES.include? ENV['FAKE_QUEUE']
|
28
|
+
end
|
29
|
+
|
30
|
+
def real_queue
|
31
|
+
Nsq if should_use_real_queue?
|
32
|
+
end
|
33
|
+
|
34
|
+
def should_use_fake_queue?
|
35
|
+
TRUTHY_VALUES.include? ENV['FAKE_QUEUE']
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/fastly_nsq/version.rb
CHANGED
data/lib/fastly_nsq.rb
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
require 'nsq'
|
2
|
+
require 'fastly_nsq/consumer'
|
3
|
+
require 'fastly_nsq/fake_backend'
|
4
|
+
require 'fastly_nsq/listener'
|
5
|
+
require 'fastly_nsq/message'
|
6
|
+
require 'fastly_nsq/producer'
|
7
|
+
require 'fastly_nsq/strategy'
|
8
|
+
require 'fastly_nsq/ssl_context'
|
1
9
|
require 'fastly_nsq/version'
|
2
10
|
|
3
|
-
|
11
|
+
module FastlyNsq
|
12
|
+
def self.logger=(logger)
|
13
|
+
strategy.logger = logger
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.logger
|
17
|
+
strategy.logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.strategy
|
21
|
+
Strategy.for_queue
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe FastlyNsq::Consumer do
|
4
|
+
let(:channel) { 'star_killer_base' }
|
5
|
+
let(:topic) { 'death_star' }
|
6
|
+
let(:consumer) { FastlyNsq::Consumer.new topic: topic, channel: channel }
|
7
|
+
|
8
|
+
describe 'when connected to a backend Consumer' do
|
9
|
+
let(:backend) { instance_double FastlyNsq::FakeBackend::Consumer, pop: nil, pop_without_blocking: nil, size: nil, terminate: nil }
|
10
|
+
let(:connector) { double 'Connector strategy', new: backend }
|
11
|
+
|
12
|
+
let(:consumer) do
|
13
|
+
FastlyNsq::Consumer.new topic: topic, channel: channel, connector: connector
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'forwards #pop' do
|
17
|
+
expect(backend).to receive(:pop)
|
18
|
+
consumer.pop
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'forwards #pop_without_blocking' do
|
22
|
+
expect(backend).to receive(:pop_without_blocking)
|
23
|
+
consumer.pop_without_blocking
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'forwards #size' do
|
27
|
+
expect(backend).to receive(:size)
|
28
|
+
consumer.size
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'forwards #terminate' do
|
32
|
+
expect(backend).to receive(:terminate)
|
33
|
+
consumer.terminate
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'using strategy to determine the consumer' do
|
38
|
+
module TestStrategy
|
39
|
+
module Consumer
|
40
|
+
@@never_terminated = true
|
41
|
+
|
42
|
+
module_function
|
43
|
+
|
44
|
+
def new(*_)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def terminate
|
49
|
+
raise 'Already terminated once' unless @@never_terminated
|
50
|
+
@@never_terminated = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def was_terminated
|
54
|
+
!@@never_terminated
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
before do
|
60
|
+
allow(FastlyNsq).to receive(:strategy).and_return(TestStrategy)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'instantiates a consumer via Strategy' do
|
64
|
+
consumer.terminate
|
65
|
+
expect(TestStrategy::Consumer.was_terminated).to be_truthy
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,49 +1,49 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
RSpec.describe
|
3
|
+
RSpec.describe FastlyNsq::FakeBackend do
|
4
4
|
describe '@@queue' do
|
5
5
|
it 'is initalized as an empty array' do
|
6
|
-
expect(
|
6
|
+
expect(FastlyNsq::FakeBackend.queue).to eq []
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '@@logger' do
|
11
11
|
after do
|
12
|
-
|
12
|
+
FastlyNsq::FakeBackend.logger = Logger.new(nil)
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'is initalized as an empty Ruby Logger' do
|
16
|
-
expect(
|
16
|
+
expect(FastlyNsq::FakeBackend.logger).to be_a Logger
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'can be set and retrieved' do
|
20
20
|
logger = double('some logger')
|
21
|
-
|
21
|
+
FastlyNsq::FakeBackend.logger = logger
|
22
22
|
|
23
|
-
expect(
|
23
|
+
expect(FastlyNsq::FakeBackend.logger).to eq logger
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '.reset!' do
|
28
28
|
it 'resets the fake message queue' do
|
29
|
-
|
30
|
-
expect(
|
29
|
+
FastlyNsq::FakeBackend.queue = ['hello']
|
30
|
+
expect(FastlyNsq::FakeBackend.queue.size).to eq 1
|
31
31
|
|
32
|
-
|
32
|
+
FastlyNsq::FakeBackend.reset!
|
33
33
|
|
34
|
-
expect(
|
34
|
+
expect(FastlyNsq::FakeBackend.queue).to be_empty
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
RSpec.describe
|
39
|
+
RSpec.describe FastlyNsq::FakeBackend::Producer do
|
40
40
|
let(:topic) { 'death_star' }
|
41
|
-
let(:producer) {
|
41
|
+
let(:producer) { FastlyNsq::FakeBackend::Producer.new topic: topic }
|
42
42
|
|
43
43
|
it 'adds a new message to the queue' do
|
44
44
|
producer.write('hello')
|
45
45
|
|
46
|
-
expect(
|
46
|
+
expect(FastlyNsq::FakeBackend.queue.size).to eq 1
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'has a `terminate` method which is a noop' do
|
@@ -51,18 +51,18 @@ RSpec.describe FakeMessageQueue::Producer do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
RSpec.describe
|
54
|
+
RSpec.describe FastlyNsq::FakeBackend::Message do
|
55
55
|
describe '#body' do
|
56
56
|
it 'returns the body of the message' do
|
57
57
|
topic = 'death_star'
|
58
58
|
content = 'hello'
|
59
|
-
producer =
|
59
|
+
producer = FastlyNsq::FakeBackend::Producer.new(
|
60
60
|
nsqd: ENV.fetch('NSQD_TCP_ADDRESS'),
|
61
61
|
topic: topic,
|
62
62
|
)
|
63
63
|
producer.write(content)
|
64
64
|
|
65
|
-
message =
|
65
|
+
message = FastlyNsq::FakeBackend.queue.pop
|
66
66
|
body = message.body
|
67
67
|
|
68
68
|
expect(content).to eq body
|
@@ -70,10 +70,10 @@ RSpec.describe FakeMessageQueue::Message do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
RSpec.describe
|
73
|
+
RSpec.describe FastlyNsq::FakeBackend::Consumer do
|
74
74
|
let(:topic) { 'death_star' }
|
75
75
|
let(:channel) { 'star_killer_base' }
|
76
|
-
let(:consumer) {
|
76
|
+
let(:consumer) { FastlyNsq::FakeBackend::Consumer.new topic: topic, channel: channel }
|
77
77
|
|
78
78
|
describe 'when there are no messages on the queue' do
|
79
79
|
it 'tells you there are 0 messages in the queue' do
|
@@ -81,8 +81,8 @@ RSpec.describe FakeMessageQueue::Consumer do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'blocks forever (until timeout) from #pop' do
|
84
|
-
|
85
|
-
delay =
|
84
|
+
FastlyNsq::FakeBackend.delay = 0.1
|
85
|
+
delay = FastlyNsq::FakeBackend.delay + 0.1
|
86
86
|
|
87
87
|
expect do
|
88
88
|
Timeout.timeout(delay) do
|
@@ -99,8 +99,8 @@ RSpec.describe FakeMessageQueue::Consumer do
|
|
99
99
|
end
|
100
100
|
|
101
101
|
describe 'when there is a message on the queue' do
|
102
|
-
let(:message) {
|
103
|
-
before {
|
102
|
+
let(:message) { FastlyNsq::FakeBackend::Message.new 'hello' }
|
103
|
+
before { FastlyNsq::FakeBackend.queue = [message] }
|
104
104
|
|
105
105
|
it 'tells you there are messages in the queue' do
|
106
106
|
expect(consumer.size).to eq 1
|
@@ -121,7 +121,7 @@ RSpec.describe FakeMessageQueue::Consumer do
|
|
121
121
|
|
122
122
|
describe '#terminate' do
|
123
123
|
it 'has a terminate method which is a noop' do
|
124
|
-
consumer = instance_double('
|
124
|
+
consumer = instance_double('FastlyNsq::FakeBackend::Consumer')
|
125
125
|
allow(consumer).to receive(:terminate)
|
126
126
|
end
|
127
127
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe FastlyNsq::Listener do
|
4
|
+
let(:topic) { 'testing_topic' }
|
5
|
+
let(:channel) { 'testing_channel' }
|
6
|
+
let(:consumer) { FastlyNsq::FakeBackend::Consumer.new topic: topic, channel: channel }
|
7
|
+
let(:logger) { double 'Logger', info: nil }
|
8
|
+
|
9
|
+
module TestMessageProcessor
|
10
|
+
@@messages_processed = []
|
11
|
+
Message = Struct.new(:body, :topic) do
|
12
|
+
def finish
|
13
|
+
@did_finish = true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.process(incoming_message)
|
18
|
+
@@messages_processed.push Message.new(incoming_message.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.messages_processed
|
22
|
+
@@messages_processed
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.clear
|
26
|
+
@@messages_processed = []
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:listener) do
|
31
|
+
FastlyNsq::Listener.new topic: topic,
|
32
|
+
processor: TestMessageProcessor,
|
33
|
+
consumer: consumer,
|
34
|
+
logger: logger
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:message) { TestMessageProcessor::Message.new 'this is message body' }
|
38
|
+
let(:messages_processed) { TestMessageProcessor.messages_processed }
|
39
|
+
let(:expected_message) { TestMessageProcessor::Message.new('this is message body') }
|
40
|
+
let(:expected_messages) { [expected_message] }
|
41
|
+
|
42
|
+
describe 'instantiating without a consumer' do
|
43
|
+
it 'instantiates a consumer, passing the topic and channel' do
|
44
|
+
allow(FastlyNsq::Consumer).to receive(:new)
|
45
|
+
|
46
|
+
FastlyNsq::Listener.new topic: topic,
|
47
|
+
channel: channel,
|
48
|
+
processor: TestMessageProcessor,
|
49
|
+
consumer: nil
|
50
|
+
|
51
|
+
expect(FastlyNsq::Consumer).to have_received(:new).
|
52
|
+
with(topic: topic, channel: channel)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when using the fake queue and it is empty', fake_queue: true do
|
57
|
+
before do
|
58
|
+
TestMessageProcessor.clear
|
59
|
+
FastlyNsq::FakeBackend.delay = 0.1
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'blocks on the process for longer than the check cycle' do
|
63
|
+
delay = FastlyNsq::FakeBackend.delay + 0.1
|
64
|
+
|
65
|
+
expect do
|
66
|
+
Timeout.timeout(delay) do
|
67
|
+
listener.go run_once: true
|
68
|
+
end
|
69
|
+
end.to raise_error(Timeout::Error)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'when processing next message' do
|
74
|
+
before(:each) do
|
75
|
+
TestMessageProcessor.clear
|
76
|
+
allow(consumer).to receive(:pop).and_return(message)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'processes the next message' do
|
80
|
+
listener.go run_once: true
|
81
|
+
|
82
|
+
expect(messages_processed).to eql(expected_messages)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'finishes the message' do
|
86
|
+
allow(message).to receive(:finish)
|
87
|
+
|
88
|
+
listener.go run_once: true
|
89
|
+
|
90
|
+
expect(message).to have_received(:finish).once
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'logs info for the message body' do
|
94
|
+
allow(logger).to receive(:info)
|
95
|
+
listener.go run_once: true
|
96
|
+
|
97
|
+
expect(logger).to have_received(:info).once.with(/\[NSQ\] Message Received: #{message.body}/)
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when preprocessor is provided' do
|
101
|
+
it 'calls the preprocessor' do
|
102
|
+
preprocessor_was_called = false
|
103
|
+
preprocessor = ->(*_args) { preprocessor_was_called = true }
|
104
|
+
|
105
|
+
listener = FastlyNsq::Listener.new topic: topic,
|
106
|
+
processor: TestMessageProcessor,
|
107
|
+
consumer: consumer,
|
108
|
+
logger: logger,
|
109
|
+
preprocessor: preprocessor
|
110
|
+
|
111
|
+
listener.go run_once: true
|
112
|
+
expect(preprocessor_was_called).to be_truthy
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
RSpec.describe FastlyNsq::Message do
|
5
|
+
let(:body) { { 'data' => 'goes here', 'other_field' => 'is over here' } }
|
6
|
+
let(:json_body) { body.to_json }
|
7
|
+
subject { FastlyNsq::Message.new json_body }
|
8
|
+
|
9
|
+
it 'preserves original message body as raw_body' do
|
10
|
+
expect(subject.raw_body).to eq(json_body)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'presents parsed message body as body' do
|
14
|
+
expect(subject.body).to eq(body)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'plucks data as data' do
|
18
|
+
expect(subject.data).to eq('goes here')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'aliases raw_body to to_s' do
|
22
|
+
expect(subject.to_s).to eq(json_body)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe FastlyNsq::Producer do
|
4
|
+
let(:topic) { 'death_star' }
|
5
|
+
let(:producer) { FastlyNsq::Producer.new(topic: topic) }
|
6
|
+
|
7
|
+
describe 'when connector connects to a backend Producer' do
|
8
|
+
let(:backend) { instance_double FastlyNsq::FakeBackend::Producer, write: nil, terminate: nil }
|
9
|
+
let(:connector) { double 'Connector', new: backend }
|
10
|
+
let(:producer) do
|
11
|
+
FastlyNsq::Producer.new topic: topic, connector: connector
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'forwards #write' do
|
15
|
+
expect(backend).to receive(:write).with("it's a message")
|
16
|
+
producer.write "it's a message"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'forwards #terminate' do
|
20
|
+
expect(backend).to receive(:terminate)
|
21
|
+
producer.terminate
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'using the default connector' do
|
26
|
+
module TestStrategy
|
27
|
+
module Producer
|
28
|
+
@@never_terminated = true
|
29
|
+
|
30
|
+
module_function
|
31
|
+
|
32
|
+
def new(*_)
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def terminate
|
37
|
+
raise 'Already terminated once' unless @@never_terminated
|
38
|
+
@@never_terminated = false
|
39
|
+
end
|
40
|
+
|
41
|
+
def was_terminated
|
42
|
+
!@@never_terminated
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
before do
|
48
|
+
allow(FastlyNsq).to receive(:strategy).and_return(TestStrategy)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'instantiates a producer via Strategy' do
|
52
|
+
producer.terminate
|
53
|
+
expect(TestStrategy::Producer.was_terminated).to be_truthy
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|