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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +1 -1
- data/Gemfile +0 -2
- data/README.md +56 -14
- data/Rakefile +4 -9
- data/examples/Rakefile +36 -0
- data/fastly_nsq.gemspec +1 -2
- data/lib/fastly_nsq/message_queue/consumer.rb +5 -1
- data/lib/fastly_nsq/message_queue/listener.rb +27 -4
- data/lib/fastly_nsq/message_queue/producer.rb +5 -1
- data/lib/fastly_nsq/rake_task.rb +40 -0
- data/lib/fastly_nsq/sample_message_processor.rb +16 -12
- data/lib/fastly_nsq/version.rb +1 -1
- data/{test/lib/fastly_nsq/fake_message_queue_test.rb → spec/lib/fastly_nsq/fake_message_queue_spec.rb} +12 -12
- data/{test/lib/fastly_nsq/fastly_nsq_test.rb → spec/lib/fastly_nsq/fastly_nsq_spec.rb} +3 -3
- data/spec/lib/fastly_nsq/message_queue/consumer_spec.rb +93 -0
- data/spec/lib/fastly_nsq/message_queue/listener_spec.rb +78 -0
- data/spec/lib/fastly_nsq/message_queue/producer_spec.rb +84 -0
- data/{test/lib/fastly_nsq/message_queue/strategy.rb → spec/lib/fastly_nsq/message_queue/strategy_spec.rb} +5 -7
- data/{test/lib/fastly_nsq/sample_message_processor_test.rb → spec/lib/fastly_nsq/sample_message_processor_spec.rb} +8 -22
- data/spec/spec_helper.rb +44 -0
- data/spec/support/env_helpers.rb +19 -0
- data/test/lib/fastly_nsq/rake_task_test.rb +68 -0
- metadata +17 -33
- data/test/lib/fastly_nsq/message_queue/consumer_test.rb +0 -59
- data/test/lib/fastly_nsq/message_queue/listener_test.rb +0 -45
- data/test/lib/fastly_nsq/message_queue/producer_test.rb +0 -54
- data/test/test_helper.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 325bb3dda2921106c66242e7d74c159e19b1d23a
|
4
|
+
data.tar.gz: d6db3266246c089e744efb2f16fabd0cee8349a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cda98052c9c52f8aa1fe65a4dd0a6e311530e300adbf58d1e9bc794a652ed21852c3d6928ef1bf0b98c5e043700f68b2924d4a9de7915e1b008905a3c25097ec
|
7
|
+
data.tar.gz: d58bb1d4976fd771677bf38857b3b292f4bb57fb3cd56fc26772b0761896b91dd7969712f1a9011c59b04a3307b5086b340d74e9bea64fb4a96a6e02c8f69388
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.0
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -29,7 +29,7 @@ Please use [GitHub Issues] to report bugs.
|
|
29
29
|
|
30
30
|
`fastly_nsq` is a Ruby Gem
|
31
31
|
tested against Rails `>= 4.2`
|
32
|
-
and Ruby `>= 2.0`.
|
32
|
+
and Ruby `>= 2.3.0`.
|
33
33
|
|
34
34
|
To get started,
|
35
35
|
add `fastly_nsq` to your `Gemfile`
|
@@ -52,9 +52,9 @@ write messages onto the queue:
|
|
52
52
|
|
53
53
|
```ruby
|
54
54
|
message_data = {
|
55
|
-
"event_type"
|
56
|
-
"data"
|
57
|
-
"key"
|
55
|
+
"event_type" => "heartbeat",
|
56
|
+
"data" => {
|
57
|
+
"key" => "value"
|
58
58
|
}
|
59
59
|
}
|
60
60
|
|
@@ -73,10 +73,10 @@ to your application:
|
|
73
73
|
|
74
74
|
```ruby
|
75
75
|
# for the fake
|
76
|
-
ENV['FAKE_QUEUE']
|
76
|
+
ENV['FAKE_QUEUE'] = true
|
77
77
|
|
78
78
|
# for the real thing
|
79
|
-
ENV['FAKE_QUEUE']
|
79
|
+
ENV['FAKE_QUEUE'] = false
|
80
80
|
```
|
81
81
|
|
82
82
|
### `MessageQueue::Consumer`
|
@@ -94,9 +94,10 @@ consumer = MessageQueue::Consumer.new(
|
|
94
94
|
|
95
95
|
consumer.size #=> 1
|
96
96
|
message = consumer.pop
|
97
|
-
message.body #=>'
|
97
|
+
message.body #=> "{ 'event_type': 'heartbeat','data': { 'key': 'value' } }"
|
98
98
|
message.finish
|
99
99
|
consumer.size #=> 0
|
100
|
+
consumer.terminate
|
100
101
|
```
|
101
102
|
|
102
103
|
As above,
|
@@ -117,7 +118,8 @@ MessageQueue::Listener.new(topic: topic, channel: channel).process_next_message
|
|
117
118
|
|
118
119
|
This will pop the next message
|
119
120
|
off of the queue
|
120
|
-
and send
|
121
|
+
and send the JSON text body
|
122
|
+
to `MessageProcessor.new(message_body).go`.
|
121
123
|
|
122
124
|
To initiate a blocking loop to process messages continuously:
|
123
125
|
|
@@ -132,8 +134,45 @@ This will block until
|
|
132
134
|
there is a new message on the queue,
|
133
135
|
pop the next message
|
134
136
|
off of the queue
|
135
|
-
and send it to `MessageProcessor.new(
|
137
|
+
and send it to `MessageProcessor.new(message_body).go`.
|
136
138
|
|
139
|
+
### `MessageQueue::RakeTask`
|
140
|
+
|
141
|
+
To help facilitate running the `MessageQueue::Listener` in a blocking fashion
|
142
|
+
outside your application, a simple `RakeTask` is provided.
|
143
|
+
|
144
|
+
This can be added into your `Rakefile` in one of two ways:
|
145
|
+
|
146
|
+
Using a block:
|
147
|
+
```ruby
|
148
|
+
require 'fastly_nsq'
|
149
|
+
require 'fastly_nsq/rake_task'
|
150
|
+
|
151
|
+
MessageQueue::RakeTask.new(:listen_task) do |task|
|
152
|
+
task.topic = 'some_topic'
|
153
|
+
task.channel = 'some_channel'
|
154
|
+
end
|
155
|
+
|
156
|
+
# usage:
|
157
|
+
`rake listen_task`
|
158
|
+
```
|
159
|
+
|
160
|
+
or using passed in values:
|
161
|
+
```ruby
|
162
|
+
require 'fastly_nsq'
|
163
|
+
require 'fastly_nsq/rake_task'
|
164
|
+
|
165
|
+
MessageQueue::RakeTask.new(:listen_task, [:topic, :channel])
|
166
|
+
|
167
|
+
# usage:
|
168
|
+
`rake listen_task['my_topic','my_channel']`
|
169
|
+
```
|
170
|
+
|
171
|
+
Both methods can be used at the same time with the passed in values taking
|
172
|
+
priority over block assigned values
|
173
|
+
|
174
|
+
See the [`Rakefile`](examples/Rakefile) file
|
175
|
+
for more detail.
|
137
176
|
|
138
177
|
### Real vs. Fake
|
139
178
|
|
@@ -163,15 +202,18 @@ This class needs to adhere to the following API:
|
|
163
202
|
```ruby
|
164
203
|
class MessageProcessor
|
165
204
|
# This an instance of NSQ::Message or FakeMessageQueue::Message
|
166
|
-
def initialize(
|
167
|
-
@
|
205
|
+
def initialize(message_body)
|
206
|
+
@message_body = message_body
|
168
207
|
end
|
169
208
|
|
170
209
|
def start
|
171
|
-
# Do things
|
210
|
+
# Do things
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
172
214
|
|
173
|
-
|
174
|
-
@
|
215
|
+
def message
|
216
|
+
JSON.parse(@message_body)
|
175
217
|
end
|
176
218
|
end
|
177
219
|
```
|
data/Rakefile
CHANGED
@@ -17,14 +17,6 @@ require 'rdoc/task'
|
|
17
17
|
RDoc::Task.new
|
18
18
|
task doc: :rdoc
|
19
19
|
|
20
|
-
require 'rake/testtask'
|
21
|
-
|
22
|
-
Rake::TestTask.new do |test|
|
23
|
-
test.libs << 'test'
|
24
|
-
test.pattern = 'test/**/*_test.rb'
|
25
|
-
test.verbose = true
|
26
|
-
end
|
27
|
-
|
28
20
|
require 'bundler/audit/cli'
|
29
21
|
|
30
22
|
namespace :bundler do
|
@@ -36,5 +28,8 @@ namespace :bundler do
|
|
36
28
|
end
|
37
29
|
end
|
38
30
|
|
31
|
+
require 'rspec/core/rake_task'
|
32
|
+
RSpec::Core::RakeTask.new(:spec)
|
33
|
+
|
39
34
|
task(:default).clear
|
40
|
-
task default: ['
|
35
|
+
task default: ['spec', 'bundler:audit']
|
data/examples/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fastly_nsq'
|
2
|
+
require 'fastly_nsq/rake_task'
|
3
|
+
|
4
|
+
##
|
5
|
+
# Both topic and channel will need to be passed into the rake task when
|
6
|
+
# it is called.
|
7
|
+
#
|
8
|
+
# ex: `rake listen_task[my_topic,my_channel]`
|
9
|
+
# topic will be 'my_topic' and channel will be 'my_channel'
|
10
|
+
#
|
11
|
+
MessageQueue::RakeTask.new(:listen_task, [:topic, :channel])
|
12
|
+
|
13
|
+
##
|
14
|
+
# Topic and channel can also be preset in the task by passing a block and
|
15
|
+
# assigning value like so. This is useful if you want a single purpose
|
16
|
+
# listener task.
|
17
|
+
#
|
18
|
+
# ex: `rake listen_task`
|
19
|
+
# topic will be 'some_topic' and channel will be 'some_channel'
|
20
|
+
#
|
21
|
+
MessageQueue::RakeTask.new(:listen_task) do |task|
|
22
|
+
task.topic = 'some_topic'
|
23
|
+
task.channel = 'some_channel'
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Both forms can be combine to provide defaults of a sort with the ability
|
28
|
+
# to override at time of rake call
|
29
|
+
#
|
30
|
+
# ex: `rake listen_task[altered_topic]`
|
31
|
+
# topic will be 'altered_topic' and channel will be 'some_channel'
|
32
|
+
#
|
33
|
+
MessageQueue::RakeTask.new(:listen_task, [:topic, :channel]) do |task|
|
34
|
+
task.topic = 'some_topic'
|
35
|
+
task.channel = 'some_channel'
|
36
|
+
end
|
data/fastly_nsq.gemspec
CHANGED
@@ -23,11 +23,10 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.add_development_dependency 'awesome_print', '~> 1.6'
|
24
24
|
gem.add_development_dependency 'bundler', '~> 1.10'
|
25
25
|
gem.add_development_dependency 'bundler-audit', '~> 0.4'
|
26
|
-
gem.add_development_dependency 'minitest', '~> 5.8'
|
27
26
|
gem.add_development_dependency 'pry-byebug', '~> 3.3'
|
28
27
|
gem.add_development_dependency 'rake', '~> 10.5'
|
29
28
|
gem.add_development_dependency 'rdoc', '~> 4.2'
|
30
|
-
gem.add_development_dependency 'rspec
|
29
|
+
gem.add_development_dependency 'rspec', '~> 3.4'
|
31
30
|
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
32
31
|
|
33
32
|
gem.add_dependency 'nsq-ruby', '~> 1.5.0', '>= 1.5.0'
|
@@ -6,22 +6,45 @@ module MessageQueue
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def go
|
9
|
+
Signal.trap('INT') do
|
10
|
+
shutdown
|
11
|
+
end
|
12
|
+
|
13
|
+
Signal.trap('TERM') do
|
14
|
+
shutdown
|
15
|
+
end
|
16
|
+
|
9
17
|
loop do
|
10
|
-
|
18
|
+
process_one_message
|
11
19
|
end
|
12
20
|
end
|
13
21
|
|
14
22
|
def process_next_message
|
15
|
-
|
16
|
-
|
23
|
+
process_one_message
|
24
|
+
consumer.terminate
|
17
25
|
end
|
18
26
|
|
19
27
|
private
|
20
28
|
|
29
|
+
def process_one_message
|
30
|
+
message = consumer.pop
|
31
|
+
MessageProcessor.new(message.body).go
|
32
|
+
message.finish
|
33
|
+
end
|
34
|
+
|
21
35
|
attr_reader :channel, :topic
|
22
36
|
|
23
37
|
def consumer
|
24
|
-
MessageQueue::Consumer.new(
|
38
|
+
@consumer ||= MessageQueue::Consumer.new(consumer_params).connection
|
39
|
+
end
|
40
|
+
|
41
|
+
def consumer_params
|
42
|
+
{ topic: topic, channel: channel }
|
43
|
+
end
|
44
|
+
|
45
|
+
def shutdown
|
46
|
+
consumer.terminate
|
47
|
+
exit
|
25
48
|
end
|
26
49
|
end
|
27
50
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
|
4
|
+
module MessageQueue
|
5
|
+
class RakeTask < Rake::TaskLib
|
6
|
+
attr_accessor :name, :topic, :channel
|
7
|
+
|
8
|
+
def initialize(*args, &task_block)
|
9
|
+
@name = args.shift || :begin_listening
|
10
|
+
|
11
|
+
desc 'Listen to NSQ on topic using channel' unless ::Rake.application.last_comment
|
12
|
+
|
13
|
+
task(name, *args) do |_, task_args|
|
14
|
+
RakeFileUtils.send(:verbose, verbose) do
|
15
|
+
yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
|
16
|
+
@topic = task_args[:topic] if task_args[:topic]
|
17
|
+
@channel = task_args[:channel] if task_args[:channel]
|
18
|
+
run_task
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def run_task
|
26
|
+
raise ArgumentError, "topic and channel are required. Recieved topic: #{topic} channel: #{channel}" unless topic && channel
|
27
|
+
|
28
|
+
output "Listening to the queue on topic:'#{topic}' and channel ':#{channel}'"
|
29
|
+
|
30
|
+
MessageQueue::Listener.new(topic: topic, channel: channel).go
|
31
|
+
|
32
|
+
output "... done listening to queue on topic:'#{topic}' and channel ':#{channel}'"
|
33
|
+
end
|
34
|
+
|
35
|
+
# wrapping output for stubbing in tests to avoid clobbering output...
|
36
|
+
def output(str)
|
37
|
+
puts str
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,25 +1,33 @@
|
|
1
|
-
class HeartbeatWorker
|
2
|
-
|
1
|
+
class HeartbeatWorker
|
2
|
+
def self.perform_async(_data)
|
3
|
+
# noop
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class UnknownMessageWorker
|
8
|
+
def self.perform_async(_data)
|
9
|
+
# noop
|
10
|
+
end
|
11
|
+
end
|
3
12
|
|
4
13
|
class SampleMessageProcessor
|
5
14
|
EVENT_TYPE_TO_WORKER_MAP = {
|
6
15
|
'heartbeat' => HeartbeatWorker,
|
7
16
|
}.freeze
|
8
17
|
|
9
|
-
def initialize(
|
10
|
-
@
|
18
|
+
def initialize(message_body)
|
19
|
+
@message_body = message_body
|
11
20
|
end
|
12
21
|
|
13
22
|
def go
|
14
|
-
|
15
|
-
message.finish
|
23
|
+
process_message_body
|
16
24
|
end
|
17
25
|
|
18
26
|
private
|
19
27
|
|
20
|
-
attr_reader :
|
28
|
+
attr_reader :message_body
|
21
29
|
|
22
|
-
def
|
30
|
+
def process_message_body
|
23
31
|
message_processor.perform_async(message_data)
|
24
32
|
end
|
25
33
|
|
@@ -38,8 +46,4 @@ class SampleMessageProcessor
|
|
38
46
|
def parsed_message_body
|
39
47
|
JSON.parse(message_body)
|
40
48
|
end
|
41
|
-
|
42
|
-
def message_body
|
43
|
-
message.body
|
44
|
-
end
|
45
49
|
end
|
data/lib/fastly_nsq/version.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe FakeMessageQueue do
|
3
|
+
RSpec.describe FakeMessageQueue do
|
4
4
|
describe '@@queue' do
|
5
5
|
it 'is initalized as an empty array' do
|
6
|
-
|
6
|
+
expect(FakeMessageQueue.queue).to eq []
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '.reset!' do
|
11
11
|
it 'resets the fake message queue' do
|
12
12
|
FakeMessageQueue.queue = ['hello']
|
13
|
-
|
13
|
+
expect(FakeMessageQueue.queue.size).to eq 1
|
14
14
|
|
15
15
|
FakeMessageQueue.reset!
|
16
16
|
|
17
|
-
|
17
|
+
expect(FakeMessageQueue.queue).to be_empty
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe FakeMessageQueue::Producer do
|
22
|
+
RSpec.describe FakeMessageQueue::Producer do
|
23
23
|
after do
|
24
24
|
FakeMessageQueue.reset!
|
25
25
|
end
|
@@ -34,12 +34,12 @@ describe FakeMessageQueue::Producer do
|
|
34
34
|
)
|
35
35
|
producer.write('hello')
|
36
36
|
|
37
|
-
|
37
|
+
expect(FakeMessageQueue.queue.size).to eq 1
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
describe FakeMessageQueue::Message do
|
42
|
+
RSpec.describe FakeMessageQueue::Message do
|
43
43
|
after do
|
44
44
|
FakeMessageQueue.reset!
|
45
45
|
end
|
@@ -57,12 +57,12 @@ describe FakeMessageQueue::Message do
|
|
57
57
|
message = FakeMessageQueue.queue.pop
|
58
58
|
body = message.body
|
59
59
|
|
60
|
-
|
60
|
+
expect(content).to eq body
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
describe FakeMessageQueue::Consumer do
|
65
|
+
RSpec.describe FakeMessageQueue::Consumer do
|
66
66
|
after do
|
67
67
|
FakeMessageQueue.reset!
|
68
68
|
end
|
@@ -80,7 +80,7 @@ describe FakeMessageQueue::Consumer do
|
|
80
80
|
)
|
81
81
|
queue_size = consumer.size
|
82
82
|
|
83
|
-
|
83
|
+
expect(queue_size).to eq 1
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -98,7 +98,7 @@ describe FakeMessageQueue::Consumer do
|
|
98
98
|
)
|
99
99
|
popped_message = consumer.pop
|
100
100
|
|
101
|
-
|
101
|
+
expect(popped_message). to eq message
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|