queue_worker 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ebdae0e3c3cca5415123d244b360243a9567440
4
- data.tar.gz: d56d1a2a8e244f706db17075ec7b7fd02e44f837
3
+ metadata.gz: f626efd2e37e8b59b15ed2493d51a5ebc789bee3
4
+ data.tar.gz: 19e29f12f964ca7c94f036ac1d3b35e3fe10a16d
5
5
  SHA512:
6
- metadata.gz: 6259ec0585962e44646031ef1c83c3eda99c4fc251ac81075cd5391c2dd3610f62847bfede00b56fbe6d7ec7a8dc462ef0b5c0769927f71cc321e0a99e498ad9
7
- data.tar.gz: a67fe1b6db0358fe4d44000f6d5299783b7b60555700b7275ec02209f3864d2bc5d733ec217c608e6aab3675ee2475b083e7a34d1115bd6905e895df656356eb
6
+ metadata.gz: be5e1738bcc633ed4de448738b6cfb8b475ca88c002d58947253e31ef9f48759bcf21fc816403193e099ab9f9ac7dc35f9495002593a2ec44e26c2c447dc4f14
7
+ data.tar.gz: d1033af1039fcf89cc7347a34b2fa0c88ab555f6090f764d9c9655ac798598fafa9587276fd792588e64f9547acbd55adfecfcb31cd15500f2992a5f750d42f5
@@ -1,3 +1,3 @@
1
1
  class QueueWorker
2
- VERSION = '1.0.2'
2
+ VERSION = '2.0.0'
3
3
  end
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 [Stomp::Client] client that can communicate with ActiveMQ
26
- def initialize(queue_name = nil, client = nil)
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
- @client = client
29
- @handler = proc { |args, message| load_handler_class(message.headers['destination']).new(args).call }
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(:default_subscribe_callback)
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
- handler.call(JSON.parse(message.body, symbolize_names: true), message)
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, double(Stomp::Client)) }
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(:headers) { { :ack => 'client', 'activemq.prefetchSize' => 1 } }
41
-
42
- context "when message command is not 'MESSAGE'" do
43
- let(:message) { Struct.new(:command).new('PING') }
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
- it 'does nothing' do
46
- expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
47
- expect(subject).to_not receive(:unsubscribe)
48
- expect(subject).to_not receive(:call)
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 "when message command is 'MESSAGE'" do
54
- let(:message) { Struct.new(:command, :body).new('MESSAGE', nil) }
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
- it 'unsubscribes from the -queue-' do
60
- expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
61
- expect(subject).to receive(:unsubscribe)
62
- subject.subscribe
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
- context "when message body is JSON" do
67
- before { message.body = '{}' }
71
+ context 'when a block is given' do
72
+ let(:handler_double) { double('Handler block') }
68
73
 
69
- it 'pass the -message- to +call+' do
70
- expect(subject.client).to receive(:subscribe).with("/queue/#{queue_name}", headers).and_yield(message)
71
- expect(subject).to receive(:call).with(message)
72
- subject.subscribe
73
- end
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: %({"name":"trip_advisor"}), headers: { 'destination' => '/queue/null' }) }
91
+ let(:message) { double("Stomp::Message", body: %({"class":"QueueWorker", "args": [101]}), command: 'MESSAGE', headers: { 'destination' => '/queue/null' }) }
87
92
 
88
- it 'acknowledges the message and passes it along to the handler class' do
89
- expect(subject.handler).to receive(:call).with({ name: 'trip_advisor' }, message)
90
- expect(subject).to receive(:ack).with(message)
91
- subject.call(message)
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: 1.0.2
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-29 00:00:00.000000000 Z
11
+ date: 2014-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler