queue_worker 1.0.2 → 2.0.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/lib/queue_worker/version.rb +1 -1
- data/lib/queue_worker.rb +19 -37
- data/spec/lib/queue_worker_spec.rb +56 -32
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f626efd2e37e8b59b15ed2493d51a5ebc789bee3
|
4
|
+
data.tar.gz: 19e29f12f964ca7c94f036ac1d3b35e3fe10a16d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be5e1738bcc633ed4de448738b6cfb8b475ca88c002d58947253e31ef9f48759bcf21fc816403193e099ab9f9ac7dc35f9495002593a2ec44e26c2c447dc4f14
|
7
|
+
data.tar.gz: d1033af1039fcf89cc7347a34b2fa0c88ab555f6090f764d9c9655ac798598fafa9587276fd792588e64f9547acbd55adfecfcb31cd15500f2992a5f750d42f5
|
data/lib/queue_worker/version.rb
CHANGED
data/lib/queue_worker.rb
CHANGED
@@ -18,15 +18,16 @@ class QueueWorker
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
attr_writer :client
|
21
|
+
attr_writer :client, :log
|
22
22
|
attr_accessor :queue, :handler
|
23
23
|
|
24
24
|
# @param [String] queue_name the queue to pub/sub
|
25
|
-
# @param [
|
26
|
-
|
25
|
+
# @param [#info, #warn, #error] log
|
26
|
+
# @param [Proc] block to handle the subscription callback
|
27
|
+
def initialize(queue_name = nil, log = nil, &block)
|
27
28
|
@queue = queue_name
|
28
|
-
@
|
29
|
-
@handler = proc { |
|
29
|
+
@log = log
|
30
|
+
@handler = block || proc { |body| Kernel.const_get(body[:class]).call(body[:args]) }
|
30
31
|
end
|
31
32
|
|
32
33
|
# = Publish one or more messages to a queue
|
@@ -68,11 +69,12 @@ class QueueWorker
|
|
68
69
|
|
69
70
|
# = Subscribe (listen) to a queue
|
70
71
|
#
|
72
|
+
# @param [String] queue_name specify the queue name
|
71
73
|
# @param [Integer] size specify the number of messages the block may receive without sending +ack+
|
72
74
|
# @param [Proc] block to handle the subscribe callback
|
73
|
-
def subscribe(size = 1, &block)
|
74
|
-
callback = block || method(:
|
75
|
-
client.subscribe("/queue/#{queue}", { :ack => 'client', 'activemq.prefetchSize' => size }, &callback)
|
75
|
+
def subscribe(queue_name = nil, size = 1, &block)
|
76
|
+
callback = block || method(:call)
|
77
|
+
client.subscribe("/queue/#{queue_name || queue}", { :ack => 'client', 'activemq.prefetchSize' => size }, &callback)
|
76
78
|
end
|
77
79
|
|
78
80
|
# = Subscribe to a queue for a limited time
|
@@ -82,7 +84,7 @@ class QueueWorker
|
|
82
84
|
# @param [Proc] block to handle the subscribe callback
|
83
85
|
def subscribe_with_timeout(duration, size = 1, &block)
|
84
86
|
Timeout::timeout(duration) do
|
85
|
-
subscribe(size, &block)
|
87
|
+
subscribe(nil, size, &block)
|
86
88
|
join
|
87
89
|
end
|
88
90
|
rescue Timeout::Error
|
@@ -90,13 +92,13 @@ class QueueWorker
|
|
90
92
|
end
|
91
93
|
|
92
94
|
# = Unsubscribe from the current queue
|
93
|
-
def unsubscribe
|
94
|
-
client.unsubscribe("/queue/#{queue}")
|
95
|
+
def unsubscribe(queue_name = nil)
|
96
|
+
client.unsubscribe("/queue/#{queue_name || queue}")
|
95
97
|
end
|
96
98
|
|
97
99
|
# = Unsubscribe from the current queue and close the connection
|
98
|
-
def quit
|
99
|
-
unsubscribe
|
100
|
+
def quit(queue_name = nil)
|
101
|
+
unsubscribe(queue_name)
|
100
102
|
close
|
101
103
|
end
|
102
104
|
|
@@ -109,34 +111,14 @@ class QueueWorker
|
|
109
111
|
#
|
110
112
|
# @param [Stomp::Message] message is the container object Stomp gives us for what is really a "frame" or package from the queue
|
111
113
|
def call(message)
|
112
|
-
|
114
|
+
if message.command == 'MESSAGE'
|
115
|
+
handler.call(JSON.parse(message.body, symbolize_names: true), message)
|
116
|
+
end
|
113
117
|
rescue => e
|
114
118
|
log.error(e.message) { "\n#{e.backtrace.inspect}" }
|
115
119
|
ensure
|
116
120
|
ack(message)
|
117
|
-
log.info('Processed') { message }
|
118
|
-
end
|
119
|
-
|
120
|
-
#
|
121
|
-
# Private
|
122
|
-
#
|
123
|
-
|
124
|
-
def default_subscribe_callback(message)
|
125
|
-
if message.command == 'MESSAGE'
|
126
|
-
if message.body == 'UNSUBSCRIBE'
|
127
|
-
unsubscribe
|
128
|
-
else
|
129
|
-
call(message)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# = Converts the queue name to a constant
|
135
|
-
#
|
136
|
-
# @param [String] destination_queue
|
137
|
-
#
|
138
|
-
def load_handler_class(destination_queue)
|
139
|
-
destination_queue.gsub(%r!^/?queue/!, '').camelize.constantize
|
121
|
+
log.info('Processed') { "#{message.headers['message-id']} for #{message.headers['destination']}" }
|
140
122
|
end
|
141
123
|
|
142
124
|
def client
|
@@ -2,8 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe QueueWorker, slow: true do
|
4
4
|
let(:queue_name) { 'queue_foo' }
|
5
|
+
let(:log) { Logger.new(STDOUT).tap { |x| x.level = Logger::ERROR } }
|
5
6
|
|
6
|
-
subject { described_class.new(queue_name,
|
7
|
+
subject { described_class.new(queue_name, log) }
|
8
|
+
|
9
|
+
before { allow(subject).to receive(:client).and_return(double(Stomp::Client)) }
|
7
10
|
|
8
11
|
describe '.publish' do
|
9
12
|
let(:message) { { id: 101 } }
|
@@ -37,40 +40,42 @@ describe QueueWorker, slow: true do
|
|
37
40
|
end
|
38
41
|
|
39
42
|
describe '#subscribe' do
|
40
|
-
let(:
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
let(:size) { 1 }
|
44
|
+
let(:headers) { { :ack => 'client', 'activemq.prefetchSize' => size } }
|
45
|
+
let(:message) { Struct.new(:command, :body).new('MESSAGE', '{}') }
|
46
|
+
|
47
|
+
it 'pass the -message- to +call+' do
|
48
|
+
expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
|
49
|
+
expect(subject).to receive(:call).with(message)
|
50
|
+
subject.subscribe
|
51
|
+
end
|
44
52
|
|
45
|
-
|
46
|
-
|
47
|
-
expect(subject).
|
48
|
-
expect(subject).
|
49
|
-
subject.subscribe
|
53
|
+
context 'when -queue_name- is given' do
|
54
|
+
it 'subscribes to the specified queue' do
|
55
|
+
expect(subject.client).to receive(:subscribe).with("/queue/test", headers).and_yield(message)
|
56
|
+
expect(subject).to receive(:call).with(message)
|
57
|
+
subject.subscribe('test')
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
|
-
context
|
54
|
-
let(:
|
55
|
-
|
56
|
-
context "when message body is 'UNSUBSCRIBE'" do
|
57
|
-
before { message.body = 'UNSUBSCRIBE' }
|
61
|
+
context 'when -size- is given' do
|
62
|
+
let(:size) { 5 }
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
+
it 'fetches the specified number of messages' do
|
65
|
+
expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
|
66
|
+
expect(subject).to receive(:call).with(message)
|
67
|
+
subject.subscribe(nil, size)
|
64
68
|
end
|
69
|
+
end
|
65
70
|
|
66
|
-
|
67
|
-
|
71
|
+
context 'when a block is given' do
|
72
|
+
let(:handler_double) { double('Handler block') }
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
+
it 'yields the given block instead of calling +call+' do
|
75
|
+
expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
|
76
|
+
expect(handler_double).to receive(:call).with(message)
|
77
|
+
expect(subject).to_not receive(:call)
|
78
|
+
subject.subscribe { |message| handler_double.call(message) }
|
74
79
|
end
|
75
80
|
end
|
76
81
|
end
|
@@ -83,12 +88,31 @@ describe QueueWorker, slow: true do
|
|
83
88
|
end
|
84
89
|
|
85
90
|
describe '#call' do
|
86
|
-
let(:message) { double("Stomp::Message", body: %({"
|
91
|
+
let(:message) { double("Stomp::Message", body: %({"class":"QueueWorker", "args": [101]}), command: 'MESSAGE', headers: { 'destination' => '/queue/null' }) }
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
93
|
+
context "when message command is 'MESSAGE'" do
|
94
|
+
it 'acknowledges the message and passes it along to the handler' do
|
95
|
+
expect(subject.handler).to receive(:call).with({ class: 'QueueWorker', args: [101] }, message)
|
96
|
+
expect(subject).to receive(:ack).with(message)
|
97
|
+
subject.call(message)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "when message command is not 'MESSAGE'" do
|
102
|
+
let(:message) { Struct.new(:command).new('PING') }
|
103
|
+
|
104
|
+
it 'does nothing' do
|
105
|
+
expect(subject.handler).to_not receive(:call)
|
106
|
+
expect(subject).to receive(:ack).with(message)
|
107
|
+
subject.call(message)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'default handler' do
|
112
|
+
it 'loads the :class and calls it with the message body' do
|
113
|
+
expect(QueueWorker).to receive(:call).with([101])
|
114
|
+
subject.handler.call(JSON.parse(message.body, symbolize_names: true))
|
115
|
+
end
|
92
116
|
end
|
93
117
|
end
|
94
118
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: queue_worker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Buckley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|