fastly_nsq 0.1.4 → 0.2.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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +1 -1
  5. data/Gemfile +0 -2
  6. data/README.md +56 -14
  7. data/Rakefile +4 -9
  8. data/examples/Rakefile +36 -0
  9. data/fastly_nsq.gemspec +1 -2
  10. data/lib/fastly_nsq/message_queue/consumer.rb +5 -1
  11. data/lib/fastly_nsq/message_queue/listener.rb +27 -4
  12. data/lib/fastly_nsq/message_queue/producer.rb +5 -1
  13. data/lib/fastly_nsq/rake_task.rb +40 -0
  14. data/lib/fastly_nsq/sample_message_processor.rb +16 -12
  15. data/lib/fastly_nsq/version.rb +1 -1
  16. data/{test/lib/fastly_nsq/fake_message_queue_test.rb → spec/lib/fastly_nsq/fake_message_queue_spec.rb} +12 -12
  17. data/{test/lib/fastly_nsq/fastly_nsq_test.rb → spec/lib/fastly_nsq/fastly_nsq_spec.rb} +3 -3
  18. data/spec/lib/fastly_nsq/message_queue/consumer_spec.rb +93 -0
  19. data/spec/lib/fastly_nsq/message_queue/listener_spec.rb +78 -0
  20. data/spec/lib/fastly_nsq/message_queue/producer_spec.rb +84 -0
  21. data/{test/lib/fastly_nsq/message_queue/strategy.rb → spec/lib/fastly_nsq/message_queue/strategy_spec.rb} +5 -7
  22. data/{test/lib/fastly_nsq/sample_message_processor_test.rb → spec/lib/fastly_nsq/sample_message_processor_spec.rb} +8 -22
  23. data/spec/spec_helper.rb +44 -0
  24. data/spec/support/env_helpers.rb +19 -0
  25. data/test/lib/fastly_nsq/rake_task_test.rb +68 -0
  26. metadata +17 -33
  27. data/test/lib/fastly_nsq/message_queue/consumer_test.rb +0 -59
  28. data/test/lib/fastly_nsq/message_queue/listener_test.rb +0 -45
  29. data/test/lib/fastly_nsq/message_queue/producer_test.rb +0 -54
  30. data/test/test_helper.rb +0 -49
@@ -1,10 +1,10 @@
1
- require 'test_helper'
1
+ require 'spec_helper'
2
2
  require 'fastly_nsq'
3
3
 
4
- describe FastlyNsq do
4
+ RSpec.describe FastlyNsq do
5
5
  it 'has a version number' do
6
6
  version = FastlyNsq.const_get('VERSION')
7
7
 
8
- assert(!version.empty?, 'should have a VERSION constant')
8
+ expect(version).not_to be_empty
9
9
  end
10
10
  end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe MessageQueue::Consumer do
4
+ describe '#connection' do
5
+ describe 'when using the real queue' do
6
+ it 'returns an instance of the queue consumer' do
7
+ use_real_connection do
8
+ allow(Nsq::Consumer).to receive(:new)
9
+ topic = 'death_star'
10
+ channel = 'star_killer_base'
11
+
12
+ MessageQueue::Consumer.new(topic: topic, channel: channel).connection
13
+
14
+ expect(Nsq::Consumer).to have_received(:new).
15
+ with(
16
+ nsqlookupd: ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS'),
17
+ topic: topic,
18
+ channel: channel,
19
+ ).at_least(:once)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe 'when using the fake queue' do
25
+ it 'returns an instance of the queue consumer' do
26
+ use_fake_connection do
27
+ allow(FakeMessageQueue::Consumer).to receive(:new)
28
+ topic = 'death_star'
29
+ channel = 'star_killer_base'
30
+
31
+ MessageQueue::Consumer.new(topic: topic, channel: channel).connection
32
+
33
+ expect(FakeMessageQueue::Consumer).to have_received(:new).
34
+ with(
35
+ nsqlookupd: ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS'),
36
+ topic: topic,
37
+ channel: channel,
38
+ ).at_least(:once)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ describe 'when the ENV is set incorrectly' do
45
+ it 'raises with a helpful error' do
46
+ allow(ENV).to receive(:[]).with('FAKE_QUEUE').and_return('taco')
47
+ topic = 'death_star'
48
+ channel = 'star_killer_base'
49
+
50
+ consumer = MessageQueue::Consumer.new(topic: topic, channel: channel)
51
+
52
+ expect{ consumer.connection }.to raise_error(InvalidParameterError)
53
+ end
54
+ end
55
+
56
+ describe '#terminate' do
57
+ describe 'when using the real queue' do
58
+ it 'closes the connection' do
59
+ use_real_connection do
60
+ consumer = double('Consumer', connection: nil, terminate: nil)
61
+ allow(Nsq::Consumer).to receive(:new).and_return(consumer)
62
+ topic = 'death_star'
63
+ channel = 'star_killer_base'
64
+ params = { topic: topic, channel: channel }
65
+
66
+ live_consumer = MessageQueue::Consumer.new(params)
67
+ live_consumer.connection
68
+ live_consumer.terminate
69
+
70
+ expect(consumer).to have_received(:terminate)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe 'when using the fake queue' do
76
+ it 'closes the connection' do
77
+ use_fake_connection do
78
+ consumer = double('Consumer', connection: nil, terminate: nil)
79
+ allow(FakeMessageQueue::Consumer).to receive(:new).and_return(consumer)
80
+ topic = 'death_star'
81
+ channel = 'star_killer_base'
82
+ params = { topic: topic, channel: channel }
83
+
84
+ live_consumer = MessageQueue::Consumer.new(params)
85
+ live_consumer.connection
86
+ live_consumer.terminate
87
+
88
+ expect(consumer).to have_received(:terminate)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe MessageQueue::Listener do
4
+ describe '#process_next_message' do
5
+ it 'pass the topic and channel to the consumer' do
6
+ allow(SampleMessageProcessor).to receive_message_chain(:new, :go)
7
+ message = double('Message', finish: nil, body: nil)
8
+ connection = double('Connection', pop: message, terminate: nil)
9
+ consumer = double('Consumer', connection: connection)
10
+ allow(MessageQueue::Consumer).to receive(:new).and_return(consumer)
11
+ topic = 'minitest'
12
+ channel = 'northstar'
13
+
14
+ MessageQueue::Listener.new(topic: topic, channel: channel).
15
+ process_next_message
16
+
17
+ expect(MessageQueue::Consumer).to have_received(:new).
18
+ with(topic: topic, channel: channel)
19
+ end
20
+
21
+ it 'processes the message' do
22
+ process_message = double(go: nil)
23
+ allow(MessageProcessor).to receive(:new).and_return(process_message)
24
+ message_body = { data: 'value' }.to_json
25
+ message = double('Message', finish: nil, body: message_body)
26
+ connection = double('Connection', pop: message, terminate: nil)
27
+ consumer = double('Consumer', connection: connection)
28
+ allow(MessageQueue::Consumer).to receive(:new).and_return(consumer)
29
+ topic = 'minitest'
30
+ channel = 'northstar'
31
+
32
+ MessageQueue::Listener.new(topic: topic, channel: channel).
33
+ process_next_message
34
+
35
+ expect(MessageProcessor).to have_received(:new).with(message_body)
36
+ expect(process_message).to have_received(:go)
37
+ end
38
+
39
+ it 'finishes the message' do
40
+ allow(SampleMessageProcessor).to receive_message_chain(:new, :go)
41
+ message = double('Message', finish: nil, body: nil)
42
+ connection = double('Connection', pop: message, terminate: nil)
43
+ consumer = double('Consumer', connection: connection)
44
+ allow(MessageQueue::Consumer).to receive(:new).and_return(consumer)
45
+ topic = 'minitest'
46
+ channel = 'northstar'
47
+
48
+ MessageQueue::Listener.new(topic: topic, channel: channel).
49
+ process_next_message
50
+
51
+ expect(message).to have_received(:finish)
52
+ end
53
+ end
54
+
55
+ describe '#go' do
56
+ describe 'when a SIGTERM is received' do
57
+ it 'closes the consumer connection' do
58
+ allow(SampleMessageProcessor).to receive_message_chain(:new, :go)
59
+ message = double(finish: nil, body: nil)
60
+ connection = double('Connection', pop: message, terminate: nil)
61
+ consumer = double('Consumer', connection: connection)
62
+ allow(MessageQueue::Consumer).to receive(:new).and_return(consumer)
63
+ topic = 'minitest'
64
+ channel = 'northstar'
65
+
66
+ pid = fork do
67
+ MessageQueue::Listener.new(topic: topic, channel: channel).go
68
+ end
69
+
70
+ Process.kill('TERM', pid)
71
+
72
+ # Success for this test is to expect it to complete
73
+ # Note: We are not testing the SIGINT case because it orphans the test
74
+ # Ruby process and is sort of meaningless as a test.
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe MessageQueue::Producer do
4
+ describe '#connection' do
5
+ describe 'when using the real queue' do
6
+ it 'returns an instance of the queue producer' do
7
+ use_real_connection do
8
+ allow(Nsq::Producer).to receive(:new)
9
+ topic = 'death_star'
10
+
11
+ MessageQueue::Producer.new(topic: topic).connection
12
+
13
+ expect(Nsq::Producer).to have_received(:new).
14
+ with(
15
+ nsqd: ENV.fetch('NSQD_TCP_ADDRESS'),
16
+ topic: topic,
17
+ ).at_least(:once)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe 'when using the fake queue' do
23
+ it 'returns an instance of the queue producer' do
24
+ use_fake_connection do
25
+ allow(FakeMessageQueue::Producer).to receive(:new)
26
+ topic = 'death_star'
27
+
28
+ MessageQueue::Producer.new(topic: topic).connection
29
+
30
+ expect(FakeMessageQueue::Producer).to have_received(:new).
31
+ with(
32
+ nsqd: ENV.fetch('NSQD_TCP_ADDRESS'),
33
+ topic: topic,
34
+ ).at_least(:once)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe 'when the ENV is set incorrectly' do
40
+ it 'raises with a helpful error' do
41
+ allow(ENV).to receive(:[]).with('FAKE_QUEUE').and_return('taco')
42
+ topic = 'death_star'
43
+
44
+ producer = MessageQueue::Producer.new(topic: topic)
45
+
46
+ expect{ producer.connection }.to raise_error(InvalidParameterError)
47
+ end
48
+ end
49
+ end
50
+
51
+ describe '#terminate' do
52
+ describe 'when using the real queue' do
53
+ it 'closes the connection' do
54
+ use_real_connection do
55
+ producer = double('Producer', connection: nil, terminate: nil)
56
+ allow(Nsq::Producer).to receive(:new).and_return(producer)
57
+ topic = 'death_star'
58
+
59
+ live_producer = MessageQueue::Producer.new(topic: topic)
60
+ live_producer.connection
61
+ live_producer.terminate
62
+
63
+ expect(producer).to have_received(:terminate)
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'when using the fake queue' do
69
+ it 'closes the connection' do
70
+ use_fake_connection do
71
+ producer = double('Producer', connection: nil, terminate: nil)
72
+ allow(FakeMessageQueue::Producer).to receive(:new).and_return(producer)
73
+ topic = 'death_star'
74
+
75
+ live_producer = MessageQueue::Producer.new(topic: topic)
76
+ live_producer.connection
77
+ live_producer.terminate
78
+
79
+ expect(producer).to have_received(:terminate)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,6 +1,6 @@
1
- require 'test_helper'
1
+ require 'spec_helper'
2
2
 
3
- describe Strategy do
3
+ RSpec.describe Strategy do
4
4
  describe '.for_queue' do
5
5
  describe 'when using the fake queue' do
6
6
  it 'returns the strategy based on the ENV variable' do
@@ -9,7 +9,7 @@ describe Strategy do
9
9
 
10
10
  strategy = Strategy.for_queue
11
11
 
12
- assert equal FakeMessageQueue, strategy
12
+ expect(strategy).to eq FakeMessageQueue
13
13
  end
14
14
  end
15
15
  end
@@ -21,7 +21,7 @@ describe Strategy do
21
21
 
22
22
  strategy = Strategy.for_queue
23
23
 
24
- assert equal Nsq, strategy
24
+ expect(strategy).to eq Nsq
25
25
  end
26
26
  end
27
27
  end
@@ -30,9 +30,7 @@ describe Strategy do
30
30
  it 'raises with a helpful error' do
31
31
  allow(ENV).to receive(:[]).with('FAKE_QUEUE').and_return('taco')
32
32
 
33
- assert_raises(InvalidParameterError) do
34
- Strategy.for_queue
35
- end
33
+ expect{ Strategy.for_queue }.to raise_error(InvalidParameterError)
36
34
  end
37
35
  end
38
36
  end
@@ -1,40 +1,27 @@
1
- require 'test_helper'
1
+ require 'spec_helper'
2
2
 
3
- describe SampleMessageProcessor do
3
+ RSpec.describe SampleMessageProcessor do
4
4
  describe '#start' do
5
5
  it 'enqueues the appropriate message processor' do
6
6
  data = { 'key' => 'value' }
7
- body = { 'event_type' => 'heartbeat', 'data' => data }.to_json
8
- message = double('Message', body: body, finish: nil)
7
+ message_body = { 'event_type' => 'heartbeat', 'data' => data }.to_json
9
8
  allow(HeartbeatWorker).to receive(:perform_async)
10
9
 
11
- SampleMessageProcessor.new(message).go
10
+ SampleMessageProcessor.new(message_body).go
12
11
 
13
12
  expect(HeartbeatWorker).to have_received(:perform_async).with(data)
14
13
  end
15
14
 
16
- it 'finishes the message' do
17
- data = { 'key' => 'value' }
18
- body = { 'event_type' => 'heartbeat', 'data' => data }.to_json
19
- message = double('Message', body: body, finish: nil)
20
- allow(HeartbeatWorker).to receive(:perform_async)
21
-
22
- SampleMessageProcessor.new(message).go
23
-
24
- expect(message).to have_received(:finish)
25
- end
26
-
27
15
  describe 'when the message event_type is not known' do
28
16
  it 'uses the null object processor' do
29
17
  data = { 'sample_key' => 'sample value' }
30
- body = {
18
+ message_body = {
31
19
  'event_type' => 'unregistered_message_type',
32
20
  'data' => data,
33
21
  }.to_json
34
- message = double('Message', body: body, finish: nil)
35
22
  allow(UnknownMessageWorker).to receive(:perform_async)
36
23
 
37
- SampleMessageProcessor.new(message).go
24
+ SampleMessageProcessor.new(message_body).go
38
25
 
39
26
  expect(UnknownMessageWorker).to have_received(:perform_async).with(data)
40
27
  end
@@ -43,14 +30,13 @@ describe SampleMessageProcessor do
43
30
  describe 'when the message lacks an event_type' do
44
31
  it 'uses the null object processor' do
45
32
  data = { 'sample_key' => 'sample value' }
46
- body = {
33
+ message_body = {
47
34
  'not_the_event_type_key' => 'unregistered_message_type',
48
35
  'data' => data,
49
36
  }.to_json
50
- message = double('Message', body: body, finish: nil)
51
37
  allow(UnknownMessageWorker).to receive(:perform_async)
52
38
 
53
- SampleMessageProcessor.new(message).go
39
+ SampleMessageProcessor.new(message_body).go
54
40
 
55
41
  expect(UnknownMessageWorker).to have_received(:perform_async).with(data)
56
42
  end
@@ -0,0 +1,44 @@
1
+ require 'fastly_nsq'
2
+ require 'awesome_print'
3
+ require 'pry-byebug'
4
+
5
+ require_relative '../lib/fastly_nsq/sample_message_processor'
6
+ require_relative 'support/env_helpers'
7
+
8
+ MessageProcessor = SampleMessageProcessor
9
+
10
+ RSpec.configure do |config|
11
+ config.expect_with :rspec do |expectations|
12
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
13
+ end
14
+
15
+ config.mock_with :rspec do |mocks|
16
+ mocks.verify_partial_doubles = true
17
+ end
18
+
19
+ config.default_formatter = 'progress'
20
+ config.disable_monkey_patching!
21
+ config.example_status_persistence_file_path = 'spec/examples.txt'
22
+ config.filter_run :focus
23
+ config.order = :random
24
+ config.profile_examples = false
25
+ config.run_all_when_everything_filtered = true
26
+ Kernel.srand config.seed
27
+
28
+ if config.files_to_run.one?
29
+ config.default_formatter = 'doc'
30
+ end
31
+
32
+ config.before(:each) do
33
+ load_sample_environment_variables
34
+ FakeMessageQueue.reset!
35
+ end
36
+
37
+ def load_sample_environment_variables
38
+ env_file = File.open('env_configuration_for_local_gem_tests.yml')
39
+
40
+ YAML.load(env_file).each do |key, value|
41
+ ENV[key.to_s] = value
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ module EnvHelpers
2
+ def use_fake_connection
3
+ MessageQueue::TRUTHY_VALUES.each do |yes|
4
+ allow(ENV).to receive(:[]).with('FAKE_QUEUE').and_return(yes)
5
+ yield
6
+ end
7
+ end
8
+
9
+ def use_real_connection
10
+ MessageQueue::FALSY_VALUES.each do |no|
11
+ allow(ENV).to receive(:[]).with('FAKE_QUEUE').and_return(no)
12
+ yield
13
+ end
14
+ end
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.include EnvHelpers
19
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ require 'fastly_nsq/rake_task'
3
+
4
+ describe MessageQueue::RakeTask do
5
+ before(:each) do
6
+ Rake::Task['begin_listening'].clear if Rake::Task.task_defined?('begin_listening')
7
+ end
8
+
9
+ describe 'defining tasks' do
10
+ it 'creates a begin_listening task' do
11
+ MessageQueue::RakeTask.new
12
+
13
+ allow_any_instance_of(MessageQueue::RakeTask).to receive(:output) { nil }
14
+ assert_equal true, Rake::Task.task_defined?(:begin_listening)
15
+ end
16
+
17
+ it 'creates a named task' do
18
+ MessageQueue::RakeTask.new(:test_name)
19
+
20
+ allow_any_instance_of(MessageQueue::RakeTask).to receive(:output) { nil }
21
+ assert_equal true, Rake::Task.task_defined?(:test_name)
22
+ end
23
+ end
24
+
25
+ describe 'running tasks' do
26
+ it 'runs with inline options defined' do
27
+ MessageQueue::RakeTask.new(:begin_listening, [:topic, :channel])
28
+
29
+ dbl = double('go', go: nil)
30
+ expect(MessageQueue::Listener).to receive(:new).
31
+ with(topic: 'dwarf', channel: 'star').
32
+ and_return(dbl)
33
+
34
+ allow_any_instance_of(MessageQueue::RakeTask).to receive(:output) { nil }
35
+ Rake::Task['begin_listening'].execute(topic: 'dwarf', channel: 'star')
36
+ end
37
+
38
+ it 'runs with specified options if a block is given' do
39
+ MessageQueue::RakeTask.new do |task|
40
+ task.topic = 'dwarf'
41
+ task.channel = 'star'
42
+ end
43
+
44
+ dbl = double('go', go: nil)
45
+ expect(MessageQueue::Listener).to receive(:new).
46
+ with(topic: 'dwarf', channel: 'star').
47
+ and_return(dbl)
48
+
49
+ allow_any_instance_of(MessageQueue::RakeTask).to receive(:output) { nil }
50
+ Rake::Task['begin_listening'].execute(topic: 'dwarf', channel: 'star')
51
+ end
52
+
53
+ it 'uses inline over block' do
54
+ MessageQueue::RakeTask.new(:begin_listening, [:topic, :channel]) do |task|
55
+ task.topic = 'loud'
56
+ task.channel = 'noise'
57
+ end
58
+
59
+ dbl = double('go', go: nil)
60
+ expect(MessageQueue::Listener).to receive(:new).
61
+ with(topic: 'dwarf', channel: 'star').
62
+ and_return(dbl)
63
+
64
+ allow_any_instance_of(MessageQueue::RakeTask).to receive(:output) { nil }
65
+ Rake::Task['begin_listening'].execute(topic: 'dwarf', channel: 'star')
66
+ end
67
+ end
68
+ end