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 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