amq-client 0.7.0.alpha34 → 0.7.0.alpha35
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.
- data/.travis.yml +4 -0
- data/Gemfile +1 -1
- data/README.textile +1 -1
- data/bin/ci/before_build.sh +24 -0
- data/examples/eventmachine_adapter/extensions/rabbitmq/handling_confirm_select_ok.rb +2 -2
- data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +1 -1
- data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_unroutable_message.rb +1 -1
- data/lib/amq/client.rb +29 -17
- data/lib/amq/client/adapter.rb +8 -504
- data/lib/amq/client/adapters/coolio.rb +4 -282
- data/lib/amq/client/adapters/event_machine.rb +4 -382
- data/lib/amq/client/async/adapter.rb +517 -0
- data/lib/amq/client/async/adapters/coolio.rb +291 -0
- data/lib/amq/client/async/adapters/event_machine.rb +392 -0
- data/lib/amq/client/async/adapters/eventmachine.rb +1 -0
- data/lib/amq/client/async/callbacks.rb +71 -0
- data/lib/amq/client/async/channel.rb +385 -0
- data/lib/amq/client/async/entity.rb +66 -0
- data/lib/amq/client/async/exchange.rb +157 -0
- data/lib/amq/client/async/extensions/rabbitmq/basic.rb +38 -0
- data/lib/amq/client/async/extensions/rabbitmq/confirm.rb +248 -0
- data/lib/amq/client/async/queue.rb +455 -0
- data/lib/amq/client/callbacks.rb +6 -65
- data/lib/amq/client/channel.rb +4 -376
- data/lib/amq/client/entity.rb +6 -57
- data/lib/amq/client/exchange.rb +4 -148
- data/lib/amq/client/extensions/rabbitmq/basic.rb +4 -28
- data/lib/amq/client/extensions/rabbitmq/confirm.rb +5 -240
- data/lib/amq/client/queue.rb +5 -450
- data/lib/amq/client/version.rb +1 -1
- data/spec/unit/client_spec.rb +10 -30
- metadata +16 -22
data/lib/amq/client/queue.rb
CHANGED
@@ -1,453 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require "amq/client/entity"
|
4
|
-
require "amq/client/adapter"
|
5
|
-
require "amq/client/server_named_entity"
|
6
|
-
require "amq/protocol/get_response"
|
1
|
+
require "amq/client/async/queue"
|
7
2
|
|
8
3
|
module AMQ
|
9
4
|
module Client
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
include Entity
|
17
|
-
include ServerNamedEntity
|
18
|
-
extend ProtocolMethodHandlers
|
19
|
-
|
20
|
-
|
21
|
-
#
|
22
|
-
# API
|
23
|
-
#
|
24
|
-
|
25
|
-
# Qeueue name. May be server-generated or assigned directly.
|
26
|
-
attr_reader :name
|
27
|
-
|
28
|
-
# Channel this queue belongs to.
|
29
|
-
attr_reader :channel
|
30
|
-
|
31
|
-
# Consumer tag identifies subscription for message delivery. It is nil for queues that are not subscribed for messages. See AMQ::Client::Queue#subscribe.
|
32
|
-
attr_reader :consumer_tag
|
33
|
-
|
34
|
-
# @param [AMQ::Client::Adapter] AMQ networking adapter to use.
|
35
|
-
# @param [AMQ::Client::Channel] AMQ channel this queue object uses.
|
36
|
-
# @param [String] Queue name. Please note that AMQP spec does not require brokers to support Unicode for queue names.
|
37
|
-
# @api public
|
38
|
-
def initialize(connection, channel, name = AMQ::Protocol::EMPTY_STRING)
|
39
|
-
raise ArgumentError.new("queue name must not be nil; if you want broker to generate queue name for you, pass an empty string") if name.nil?
|
40
|
-
|
41
|
-
super(connection)
|
42
|
-
|
43
|
-
@name = name
|
44
|
-
@channel = channel
|
45
|
-
end
|
46
|
-
|
47
|
-
def dup
|
48
|
-
if @name.empty?
|
49
|
-
raise RuntimeError.new("You can't clone anonymous queue until it receives server-generated name. Move the code with #dup to the callback for the #declare method.")
|
50
|
-
end
|
51
|
-
|
52
|
-
o = super
|
53
|
-
o.reset_consumer_tag!
|
54
|
-
o
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
# @return [Boolean] true if this queue was declared as durable (will survive broker restart).
|
59
|
-
# @api public
|
60
|
-
def durable?
|
61
|
-
@durable
|
62
|
-
end # durable?
|
63
|
-
|
64
|
-
# @return [Boolean] true if this queue was declared as exclusive (limited to just one consumer)
|
65
|
-
# @api public
|
66
|
-
def exclusive?
|
67
|
-
@exclusive
|
68
|
-
end # exclusive?
|
69
|
-
|
70
|
-
# @return [Boolean] true if this queue was declared as automatically deleted (deleted as soon as last consumer unbinds).
|
71
|
-
# @api public
|
72
|
-
def auto_delete?
|
73
|
-
@auto_delete
|
74
|
-
end # auto_delete?
|
75
|
-
|
76
|
-
|
77
|
-
# Declares this queue.
|
78
|
-
#
|
79
|
-
#
|
80
|
-
# @return [Queue] self
|
81
|
-
#
|
82
|
-
# @api public
|
83
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.7.2.1.)
|
84
|
-
def declare(passive = false, durable = false, exclusive = false, auto_delete = false, nowait = false, arguments = nil, &block)
|
85
|
-
raise ArgumentError, "declaration with nowait does not make sense for server-named queues! Either specify name other than empty string or use #declare without nowait" if nowait && self.anonymous?
|
86
|
-
|
87
|
-
@durable = durable
|
88
|
-
@exclusive = exclusive
|
89
|
-
@auto_delete = auto_delete
|
90
|
-
|
91
|
-
nowait = true if !block && !@name.empty?
|
92
|
-
@connection.send_frame(Protocol::Queue::Declare.encode(@channel.id, @name, passive, durable, exclusive, auto_delete, nowait, arguments))
|
93
|
-
|
94
|
-
if !nowait
|
95
|
-
self.append_callback(:declare, &block)
|
96
|
-
@channel.queues_awaiting_declare_ok.push(self)
|
97
|
-
end
|
98
|
-
|
99
|
-
self
|
100
|
-
end
|
101
|
-
|
102
|
-
# Deletes this queue.
|
103
|
-
#
|
104
|
-
# @param [Boolean] if_unused delete only if queue has no consumers (subscribers).
|
105
|
-
# @param [Boolean] if_empty delete only if queue has no messages in it.
|
106
|
-
# @param [Boolean] nowait Don't wait for reply from broker.
|
107
|
-
# @return [Queue] self
|
108
|
-
#
|
109
|
-
# @api public
|
110
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.7.2.9.)
|
111
|
-
def delete(if_unused = false, if_empty = false, nowait = false, &block)
|
112
|
-
nowait = true unless block
|
113
|
-
@connection.send_frame(Protocol::Queue::Delete.encode(@channel.id, @name, if_unused, if_empty, nowait))
|
114
|
-
|
115
|
-
if !nowait
|
116
|
-
self.append_callback(:delete, &block)
|
117
|
-
|
118
|
-
# TODO: delete itself from queues cache
|
119
|
-
@channel.queues_awaiting_delete_ok.push(self)
|
120
|
-
end
|
121
|
-
|
122
|
-
self
|
123
|
-
end # delete(channel, queue, if_unused, if_empty, nowait, &block)
|
124
|
-
|
125
|
-
#
|
126
|
-
# @return [Queue] self
|
127
|
-
#
|
128
|
-
# @api public
|
129
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.7.2.3.)
|
130
|
-
def bind(exchange, routing_key = AMQ::Protocol::EMPTY_STRING, nowait = false, arguments = nil, &block)
|
131
|
-
nowait = true unless block
|
132
|
-
exchange_name = if exchange.respond_to?(:name)
|
133
|
-
exchange.name
|
134
|
-
else
|
135
|
-
|
136
|
-
exchange
|
137
|
-
end
|
138
|
-
|
139
|
-
@connection.send_frame(Protocol::Queue::Bind.encode(@channel.id, @name, exchange_name, routing_key, nowait, arguments))
|
140
|
-
|
141
|
-
if !nowait
|
142
|
-
self.append_callback(:bind, &block)
|
143
|
-
|
144
|
-
# TODO: handle channel & connection-level exceptions
|
145
|
-
@channel.queues_awaiting_bind_ok.push(self)
|
146
|
-
end
|
147
|
-
|
148
|
-
self
|
149
|
-
end
|
150
|
-
|
151
|
-
#
|
152
|
-
# @return [Queue] self
|
153
|
-
#
|
154
|
-
# @api public
|
155
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.7.2.5.)
|
156
|
-
def unbind(exchange, routing_key = AMQ::Protocol::EMPTY_STRING, arguments = nil, &block)
|
157
|
-
exchange_name = if exchange.respond_to?(:name)
|
158
|
-
exchange.name
|
159
|
-
else
|
160
|
-
|
161
|
-
exchange
|
162
|
-
end
|
163
|
-
|
164
|
-
@connection.send_frame(Protocol::Queue::Unbind.encode(@channel.id, @name, exchange_name, routing_key, arguments))
|
165
|
-
|
166
|
-
self.append_callback(:unbind, &block)
|
167
|
-
# TODO: handle channel & connection-level exceptions
|
168
|
-
@channel.queues_awaiting_unbind_ok.push(self)
|
169
|
-
|
170
|
-
self
|
171
|
-
end
|
172
|
-
|
173
|
-
|
174
|
-
#
|
175
|
-
# @return [Queue] self
|
176
|
-
#
|
177
|
-
# @api public
|
178
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.3.)
|
179
|
-
def consume(no_ack = false, exclusive = false, nowait = false, no_local = false, arguments = nil, &block)
|
180
|
-
raise RuntimeError.new("This instance is already being consumed! Create another one using #dup.") if @consumer_tag
|
181
|
-
|
182
|
-
nowait = true unless block
|
183
|
-
@consumer_tag = generate_consumer_tag(name)
|
184
|
-
@connection.send_frame(Protocol::Basic::Consume.encode(@channel.id, @name, @consumer_tag, no_local, no_ack, exclusive, nowait, arguments))
|
185
|
-
|
186
|
-
@channel.consumers[@consumer_tag] = self
|
187
|
-
|
188
|
-
if !nowait
|
189
|
-
# unlike #get, here it is reasonable to expect more than one callback
|
190
|
-
# so we use #append_callback
|
191
|
-
self.append_callback(:consume, &block)
|
192
|
-
|
193
|
-
@channel.queues_awaiting_consume_ok.push(self)
|
194
|
-
end
|
195
|
-
|
196
|
-
self
|
197
|
-
end
|
198
|
-
|
199
|
-
# Unique string supposed to be used as a consumer tag.
|
200
|
-
#
|
201
|
-
# @return [String] Unique string.
|
202
|
-
# @api plugin
|
203
|
-
def generate_consumer_tag(name)
|
204
|
-
"#{name}-#{Time.now.to_i * 1000}-#{Kernel.rand(999_999_999_999)}"
|
205
|
-
end
|
206
|
-
|
207
|
-
# Resets consumer tag by setting it to nil.
|
208
|
-
# @return [String] Consumer tag this queue previously used.
|
209
|
-
#
|
210
|
-
# @api plugin
|
211
|
-
def reset_consumer_tag!
|
212
|
-
ct = @consumer_tag.dup
|
213
|
-
@consumer_tag = nil
|
214
|
-
|
215
|
-
ct
|
216
|
-
end
|
217
|
-
|
218
|
-
|
219
|
-
#
|
220
|
-
# @return [Queue] self
|
221
|
-
#
|
222
|
-
# @api public
|
223
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.10.)
|
224
|
-
def get(no_ack = false, &block)
|
225
|
-
@connection.send_frame(Protocol::Basic::Get.encode(@channel.id, @name, no_ack))
|
226
|
-
|
227
|
-
# most people only want one callback per #get call. Consider the following example:
|
228
|
-
#
|
229
|
-
# 100.times { queue.get { ... } }
|
230
|
-
#
|
231
|
-
# most likely you won't expect 100 callback runs per message here. MK.
|
232
|
-
self.redefine_callback(:get, &block)
|
233
|
-
@channel.queues_awaiting_get_response.push(self)
|
234
|
-
|
235
|
-
self
|
236
|
-
end # get(no_ack = false, &block)
|
237
|
-
|
238
|
-
#
|
239
|
-
# @return [Queue] self
|
240
|
-
#
|
241
|
-
# @api public
|
242
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.5.)
|
243
|
-
def cancel(nowait = false, &block)
|
244
|
-
raise "There is no consumer tag for this queue. This usually means that you are trying to unsubscribe a queue that never was subscribed for messages in the first place." if @consumer_tag.nil?
|
245
|
-
|
246
|
-
@connection.send_frame(Protocol::Basic::Cancel.encode(@channel.id, @consumer_tag, nowait))
|
247
|
-
@consumer_tag = nil
|
248
|
-
self.clear_callbacks(:delivery)
|
249
|
-
self.clear_callbacks(:consume)
|
250
|
-
|
251
|
-
if !nowait
|
252
|
-
self.redefine_callback(:cancel, &block)
|
253
|
-
@channel.queues_awaiting_cancel_ok.push(self)
|
254
|
-
end
|
255
|
-
|
256
|
-
self
|
257
|
-
end # cancel(&block)
|
258
|
-
|
259
|
-
#
|
260
|
-
# @return [Queue] self
|
261
|
-
#
|
262
|
-
# @api public
|
263
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.7.2.7.)
|
264
|
-
def purge(nowait = false, &block)
|
265
|
-
nowait = true unless block
|
266
|
-
@connection.send_frame(Protocol::Queue::Purge.encode(@channel.id, @name, nowait))
|
267
|
-
|
268
|
-
if !nowait
|
269
|
-
self.redefine_callback(:purge, &block)
|
270
|
-
# TODO: handle channel & connection-level exceptions
|
271
|
-
@channel.queues_awaiting_purge_ok.push(self)
|
272
|
-
end
|
273
|
-
|
274
|
-
self
|
275
|
-
end # purge(nowait = false, &block)
|
276
|
-
|
277
|
-
#
|
278
|
-
# @return [Queue] self
|
279
|
-
#
|
280
|
-
# @api public
|
281
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.13.)
|
282
|
-
def acknowledge(delivery_tag)
|
283
|
-
@channel.acknowledge(delivery_tag)
|
284
|
-
|
285
|
-
self
|
286
|
-
end # acknowledge(delivery_tag)
|
287
|
-
|
288
|
-
#
|
289
|
-
# @return [Queue] self
|
290
|
-
#
|
291
|
-
# @api public
|
292
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.14.)
|
293
|
-
def reject(delivery_tag, requeue = true)
|
294
|
-
@channel.reject(delivery_tag, requeue)
|
295
|
-
|
296
|
-
self
|
297
|
-
end # reject(delivery_tag, requeue = true)
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
# @api public
|
302
|
-
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Sections 1.8.3.9)
|
303
|
-
def on_delivery(&block)
|
304
|
-
self.append_callback(:delivery, &block)
|
305
|
-
end # on_delivery(&block)
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
#
|
310
|
-
# Implementation
|
311
|
-
#
|
312
|
-
|
313
|
-
def handle_declare_ok(method)
|
314
|
-
@name = method.queue if self.anonymous?
|
315
|
-
@channel.register_queue(self)
|
316
|
-
|
317
|
-
self.exec_callback_once_yielding_self(:declare, method)
|
318
|
-
end
|
319
|
-
|
320
|
-
def handle_delete_ok(method)
|
321
|
-
self.exec_callback_once(:delete, method)
|
322
|
-
end # handle_delete_ok(method)
|
323
|
-
|
324
|
-
def handle_consume_ok(method)
|
325
|
-
self.exec_callback_once(:consume, method)
|
326
|
-
end # handle_consume_ok(method)
|
327
|
-
|
328
|
-
def handle_purge_ok(method)
|
329
|
-
self.exec_callback_once(:purge, method)
|
330
|
-
end # handle_purge_ok(method)
|
331
|
-
|
332
|
-
def handle_bind_ok(method)
|
333
|
-
self.exec_callback_once(:bind, method)
|
334
|
-
end # handle_bind_ok(method)
|
335
|
-
|
336
|
-
def handle_unbind_ok(method)
|
337
|
-
self.exec_callback_once(:unbind, method)
|
338
|
-
end # handle_unbind_ok(method)
|
339
|
-
|
340
|
-
def handle_delivery(method, header, payload)
|
341
|
-
self.exec_callback(:delivery, method, header, payload)
|
342
|
-
end # handle_delivery
|
343
|
-
|
344
|
-
def handle_cancel_ok(method)
|
345
|
-
@consumer_tag = nil
|
346
|
-
self.exec_callback_once(:cancel, method)
|
347
|
-
end # handle_cancel_ok(method)
|
348
|
-
|
349
|
-
def handle_get_ok(method, header, payload)
|
350
|
-
method = Protocol::GetResponse.new(method)
|
351
|
-
self.exec_callback(:get, method, header, payload)
|
352
|
-
end # handle_get_ok(method, header, payload)
|
353
|
-
|
354
|
-
def handle_get_empty(method)
|
355
|
-
method = Protocol::GetResponse.new(method)
|
356
|
-
self.exec_callback(:get, method)
|
357
|
-
end # handle_get_empty(method)
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
# Get the first queue which didn't receive Queue.Declare-Ok yet and run its declare callback.
|
362
|
-
# The cache includes only queues with {nowait: false}.
|
363
|
-
self.handle(Protocol::Queue::DeclareOk) do |connection, frame|
|
364
|
-
method = frame.decode_payload
|
365
|
-
|
366
|
-
channel = connection.channels[frame.channel]
|
367
|
-
queue = channel.queues_awaiting_declare_ok.shift
|
368
|
-
|
369
|
-
queue.handle_declare_ok(method)
|
370
|
-
end
|
371
|
-
|
372
|
-
|
373
|
-
self.handle(Protocol::Queue::DeleteOk) do |connection, frame|
|
374
|
-
channel = connection.channels[frame.channel]
|
375
|
-
queue = channel.queues_awaiting_delete_ok.shift
|
376
|
-
queue.handle_delete_ok(frame.decode_payload)
|
377
|
-
end
|
378
|
-
|
379
|
-
|
380
|
-
self.handle(Protocol::Queue::BindOk) do |connection, frame|
|
381
|
-
channel = connection.channels[frame.channel]
|
382
|
-
queue = channel.queues_awaiting_bind_ok.shift
|
383
|
-
|
384
|
-
queue.handle_bind_ok(frame.decode_payload)
|
385
|
-
end
|
386
|
-
|
387
|
-
|
388
|
-
self.handle(Protocol::Queue::UnbindOk) do |connection, frame|
|
389
|
-
channel = connection.channels[frame.channel]
|
390
|
-
queue = channel.queues_awaiting_unbind_ok.shift
|
391
|
-
|
392
|
-
queue.handle_unbind_ok(frame.decode_payload)
|
393
|
-
end
|
394
|
-
|
395
|
-
|
396
|
-
self.handle(Protocol::Basic::ConsumeOk) do |connection, frame|
|
397
|
-
channel = connection.channels[frame.channel]
|
398
|
-
queue = channel.queues_awaiting_consume_ok.shift
|
399
|
-
|
400
|
-
queue.handle_consume_ok(frame.decode_payload)
|
401
|
-
end
|
402
|
-
|
403
|
-
|
404
|
-
self.handle(Protocol::Basic::CancelOk) do |connection, frame|
|
405
|
-
channel = connection.channels[frame.channel]
|
406
|
-
queue = channel.queues_awaiting_cancel_ok.shift
|
407
|
-
|
408
|
-
queue.handle_consume_ok(frame.decode_payload)
|
409
|
-
end
|
410
|
-
|
411
|
-
|
412
|
-
# Basic.Deliver
|
413
|
-
self.handle(Protocol::Basic::Deliver) do |connection, method_frame, content_frames|
|
414
|
-
channel = connection.channels[method_frame.channel]
|
415
|
-
method = method_frame.decode_payload
|
416
|
-
queue = channel.consumers[method.consumer_tag]
|
417
|
-
|
418
|
-
header = content_frames.shift
|
419
|
-
body = content_frames.map { |frame| frame.payload }.join
|
420
|
-
queue.handle_delivery(method, header, body)
|
421
|
-
# TODO: ack if necessary
|
422
|
-
end
|
423
|
-
|
424
|
-
|
425
|
-
self.handle(Protocol::Queue::PurgeOk) do |connection, frame|
|
426
|
-
channel = connection.channels[frame.channel]
|
427
|
-
queue = channel.queues_awaiting_purge_ok.shift
|
428
|
-
|
429
|
-
queue.handle_purge_ok(frame.decode_payload)
|
430
|
-
end
|
431
|
-
|
432
|
-
|
433
|
-
self.handle(Protocol::Basic::GetOk) do |connection, frame, content_frames|
|
434
|
-
channel = connection.channels[frame.channel]
|
435
|
-
queue = channel.queues_awaiting_get_response.shift
|
436
|
-
method = frame.decode_payload
|
437
|
-
|
438
|
-
header = content_frames.shift
|
439
|
-
body = content_frames.map {|frame| frame.payload }.join
|
440
|
-
|
441
|
-
queue.handle_get_ok(method, header, body) if queue
|
442
|
-
end
|
443
|
-
|
444
|
-
|
445
|
-
self.handle(Protocol::Basic::GetEmpty) do |connection, frame|
|
446
|
-
channel = connection.channels[frame.channel]
|
447
|
-
queue = channel.queues_awaiting_get_response.shift
|
448
|
-
|
449
|
-
queue.handle_get_empty(frame.decode_payload)
|
450
|
-
end
|
451
|
-
end # Queue
|
452
|
-
end # Client
|
453
|
-
end # AMQ
|
5
|
+
Queue = Async::Queue
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|