lapine 1.1.3 → 1.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/lib/lapine/consumer/config.rb +4 -0
- data/lib/lapine/consumer/runner.rb +67 -12
- data/lib/lapine/consumer/topology.rb +16 -6
- data/lib/lapine/version.rb +1 -1
- data/spec/lib/lapine/consumer/config_spec.rb +17 -0
- data/spec/lib/lapine/consumer/runner_spec.rb +2 -0
- data/spec/lib/lapine/consumer/topology_spec.rb +37 -16
- data/spec/spec_helper.rb +2 -0
- 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: 606eec9764b4ad0c59adde34f12ba6eac251657a
|
4
|
+
data.tar.gz: 2acceab836b17cfe7a7c8121c149d6a176ebb7e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc643eec3ba896154c77828b7db6833c4eb2d11f018fb27a8fbb65490a3e2a9f3d246fef82292a3274910d60c1ffa7f2d6b04fe07f95bd8d1924076618d894c5
|
7
|
+
data.tar.gz: 06e26f733603299950b18f2b499d1d7ea3ca83a767b2677dd52c7429579df9580abf3997dec658a2b3a212f22cf39719bb319f5012f138b0a12003aef565793f
|
@@ -28,23 +28,28 @@ module Lapine
|
|
28
28
|
|
29
29
|
@queue_properties = queue_properties
|
30
30
|
EventMachine.run do
|
31
|
-
topology.each_binding do |q, conn, routing_key,
|
31
|
+
topology.each_binding do |q, conn, routing_key, handlers|
|
32
32
|
queue = conn.channel.queue(q, @queue_properties).bind(conn.exchange, routing_key: routing_key)
|
33
33
|
queue.subscribe(ack: true) do |metadata, payload|
|
34
|
+
process(metadata, payload, handlers)
|
35
|
+
EventMachine.stop_event_loop if should_exit?
|
36
|
+
end
|
37
|
+
queues << queue
|
38
|
+
end
|
34
39
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
topology.each_queue_to_delete do |q, conn, routing_key, handlers|
|
41
|
+
# if queue does not exist in RabbitMQ, skip processing
|
42
|
+
# else
|
43
|
+
queue = conn.channel.queue(q, @queue_properties)
|
44
|
+
queues_to_delete << queue
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
46
|
+
queue.subscribe(ack: true) do |metadata, payload|
|
47
|
+
process(metadata, payload, handlers)
|
48
|
+
end
|
46
49
|
|
47
|
-
|
50
|
+
EventMachine.add_timer(0.5) do
|
51
|
+
logger.info "Lapine::Consumer unbinding #{queue.name} from exchange: #{exchange.name}, routing_key: #{routing_key}"
|
52
|
+
queue.unbind(conn.exchange, routing_key: routing_key)
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
@@ -58,6 +63,8 @@ module Lapine
|
|
58
63
|
EventMachine.add_periodic_timer(5) do
|
59
64
|
EventMachine.stop_event_loop if should_exit?
|
60
65
|
end
|
66
|
+
|
67
|
+
schedule_queue_deletion
|
61
68
|
end
|
62
69
|
|
63
70
|
logger.warn 'exiting Lapine::Consumer'
|
@@ -90,6 +97,54 @@ module Lapine
|
|
90
97
|
Signal.trap('INT') { EventMachine.stop }
|
91
98
|
Signal.trap('TERM') { $STOP_LAPINE_CONSUMER = true }
|
92
99
|
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def queues
|
104
|
+
@queues ||= []
|
105
|
+
end
|
106
|
+
|
107
|
+
def queues_to_delete
|
108
|
+
@queues_to_delete ||= []
|
109
|
+
end
|
110
|
+
|
111
|
+
def schedule_queue_deletion
|
112
|
+
EventMachine.add_timer(30) do
|
113
|
+
queues_to_delete.each do |queue|
|
114
|
+
logger.info "Lapine::Consumer checking #{queue.name} for deletion"
|
115
|
+
|
116
|
+
begin
|
117
|
+
queue.status do |message_count, consumer_count|
|
118
|
+
if message_count == 0
|
119
|
+
logger.info "Lapine::Consumer deleting #{queue.name}"
|
120
|
+
queue.unsubscribe
|
121
|
+
queue.delete unless config.transient?
|
122
|
+
queues_to_delete.delete(queue)
|
123
|
+
else
|
124
|
+
logger.info "Lapine::Consumer skipping #{queue.name} deletion, message count: #{message_count}"
|
125
|
+
schedule_queue_deletion
|
126
|
+
end
|
127
|
+
end
|
128
|
+
rescue => e
|
129
|
+
logger.error "Unable to delete queue #{queue.name}, error: #{e.message}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def process(metadata, payload, handlers)
|
136
|
+
message = Consumer::Message.new(payload, metadata, logger)
|
137
|
+
Middleware.app.call(message) do |message|
|
138
|
+
handlers.each do |handler|
|
139
|
+
Lapine::Consumer::Dispatcher.new(handler, message).dispatch
|
140
|
+
end
|
141
|
+
|
142
|
+
if config.debug?
|
143
|
+
@message_count += 1
|
144
|
+
@running_message_count += 1
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
93
148
|
end
|
94
149
|
end
|
95
150
|
end
|
@@ -6,16 +6,17 @@ module Lapine
|
|
6
6
|
|
7
7
|
def each_binding
|
8
8
|
config.queues.each do |node|
|
9
|
-
classes = node['handlers']
|
10
|
-
handler.split('::').inject(Object) do |const, name|
|
11
|
-
const.const_get(name)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
9
|
+
classes = classify(node['handlers'])
|
15
10
|
yield node['q'], get_conn(node['topic']), node['routing_key'], classes
|
16
11
|
end
|
17
12
|
end
|
18
13
|
|
14
|
+
def each_queue_to_delete
|
15
|
+
config.delete_queues.each do |node|
|
16
|
+
classes = classify(node['handlers'])
|
17
|
+
yield node['q'], get_conn(node['topic']), node['routing_key'], classes
|
18
|
+
end
|
19
|
+
end
|
19
20
|
|
20
21
|
def each_topic
|
21
22
|
config.topics.each do |topic|
|
@@ -32,6 +33,15 @@ module Lapine
|
|
32
33
|
|
33
34
|
private
|
34
35
|
|
36
|
+
def classify(handlers)
|
37
|
+
return [] unless handlers
|
38
|
+
handlers.map do |handler|
|
39
|
+
handler.split('::').inject(Object) do |const, name|
|
40
|
+
const.const_get(name)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
35
45
|
def get_conn(name)
|
36
46
|
@cons ||= {}.tap do |cons|
|
37
47
|
each_topic do |topic|
|
data/lib/lapine/version.rb
CHANGED
@@ -170,6 +170,23 @@ RSpec.describe Lapine::Consumer::Config do
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
+
describe '#delete_queues' do
|
174
|
+
let(:config_from_file) { {} }
|
175
|
+
|
176
|
+
it 'defaults to empty array' do
|
177
|
+
expect(config.delete_queues).to eq([])
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'with an array' do
|
181
|
+
let(:config_from_file) { {'delete_queues' => ['a.b.c', 'e.f.g']} }
|
182
|
+
|
183
|
+
it 'reads from config' do
|
184
|
+
expect(config.delete_queues).to eq(['a.b.c', 'e.f.g'])
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
173
190
|
describe '#transient?' do
|
174
191
|
it 'is false by default' do
|
175
192
|
expect(config.transient?).to be false
|
@@ -39,11 +39,13 @@ RSpec.describe Lapine::Consumer::Runner do
|
|
39
39
|
connection_properties: connection_properties,
|
40
40
|
require: [],
|
41
41
|
queues: queues,
|
42
|
+
delete_queues: delete_queues,
|
42
43
|
topics: ['testing.topic'],
|
43
44
|
debug?: true,
|
44
45
|
transient?: true) }
|
45
46
|
let(:connection_properties) { {host: '127.0.0.1', port: 5672, ssl: false, vhost: '/', username: 'guest', password: 'guest'} }
|
46
47
|
let(:message) { Oj.dump({'pay' => 'load'}) }
|
48
|
+
let(:delete_queues) { [] }
|
47
49
|
|
48
50
|
describe '#run' do
|
49
51
|
before do
|
@@ -9,26 +9,27 @@ RSpec.describe Lapine::Consumer::Topology do
|
|
9
9
|
|
10
10
|
let(:topics) {
|
11
11
|
[
|
12
|
-
|
13
|
-
|
12
|
+
'a.topic',
|
13
|
+
'b.topic'
|
14
14
|
]
|
15
15
|
}
|
16
16
|
let(:queues) {
|
17
17
|
[{
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"handlers" => ["MessageBusTest::Clazz"]
|
18
|
+
'q' => 'store.buyable',
|
19
|
+
'topic' => 'a.topic',
|
20
|
+
'routing_key' => 'store.buyable.update',
|
21
|
+
'handlers' => ['MessageBusTest::Clazz']
|
23
22
|
}]
|
24
23
|
}
|
25
24
|
let(:connection_properties) {
|
26
25
|
{}
|
27
26
|
}
|
27
|
+
let(:queues_to_delete) { [] }
|
28
28
|
let(:config) do
|
29
29
|
double('config',
|
30
30
|
topics: topics,
|
31
31
|
queues: queues,
|
32
|
+
delete_queues: queues_to_delete,
|
32
33
|
connection_properties: connection_properties,
|
33
34
|
debug?: debug)
|
34
35
|
end
|
@@ -37,33 +38,53 @@ RSpec.describe Lapine::Consumer::Topology do
|
|
37
38
|
let(:debug) { false }
|
38
39
|
let(:logger) { nil }
|
39
40
|
|
40
|
-
describe
|
41
|
-
it
|
41
|
+
describe '#each_topic' do
|
42
|
+
it 'yields correct dount' do
|
42
43
|
expect { |b| topology.each_topic(&b) }.to yield_control.twice
|
43
44
|
end
|
44
45
|
|
45
|
-
it
|
46
|
-
expect { |b| topology.each_topic(&b) }.to yield_successive_args(
|
46
|
+
it 'yields all topics in order' do
|
47
|
+
expect { |b| topology.each_topic(&b) }.to yield_successive_args('a.topic', 'b.topic')
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
describe
|
51
|
+
describe '#each_queue_to_delete' do
|
52
|
+
let(:conn) { double('connection') }
|
53
|
+
let(:queues_to_delete) { [
|
54
|
+
{'q' => 'queue.name', 'topic' => 'a.topic', 'handlers' => ['MessageBusTest::Clazz']},
|
55
|
+
{'q' => 'other.queue.name', 'topic' => 'a.topic', 'handlers' => ['MessageBusTest::Clazz']}
|
56
|
+
] }
|
57
|
+
before do
|
58
|
+
allow(Lapine::Consumer::Connection).to receive(:new) { conn }
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'yields queue name with connection' do
|
62
|
+
expect { |b|
|
63
|
+
topology.each_queue_to_delete(&b)
|
64
|
+
}.to yield_successive_args(
|
65
|
+
['queue.name', conn, nil, [MessageBusTest::Clazz]],
|
66
|
+
['other.queue.name', conn, nil, [MessageBusTest::Clazz]]
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#each_binding' do
|
51
72
|
let(:conn) { double('connection') }
|
52
73
|
|
53
74
|
before do
|
54
75
|
allow(Lapine::Consumer::Connection).to receive(:new) { conn }
|
55
76
|
end
|
56
77
|
|
57
|
-
it
|
78
|
+
it 'yields correct count' do
|
58
79
|
expect { |b| topology.each_binding(&b) }.to yield_control.once
|
59
80
|
end
|
60
81
|
|
61
|
-
it
|
82
|
+
it 'yields expected arguments' do
|
62
83
|
expect { |b|
|
63
84
|
topology.each_binding(&b)
|
64
|
-
}.to yield_with_args(
|
85
|
+
}.to yield_with_args('store.buyable',
|
65
86
|
conn,
|
66
|
-
|
87
|
+
'store.buyable.update',
|
67
88
|
[MessageBusTest::Clazz])
|
68
89
|
end
|
69
90
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lapine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Saxby
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: amqp
|