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.
Files changed (32) hide show
  1. data/.travis.yml +4 -0
  2. data/Gemfile +1 -1
  3. data/README.textile +1 -1
  4. data/bin/ci/before_build.sh +24 -0
  5. data/examples/eventmachine_adapter/extensions/rabbitmq/handling_confirm_select_ok.rb +2 -2
  6. data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +1 -1
  7. data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_unroutable_message.rb +1 -1
  8. data/lib/amq/client.rb +29 -17
  9. data/lib/amq/client/adapter.rb +8 -504
  10. data/lib/amq/client/adapters/coolio.rb +4 -282
  11. data/lib/amq/client/adapters/event_machine.rb +4 -382
  12. data/lib/amq/client/async/adapter.rb +517 -0
  13. data/lib/amq/client/async/adapters/coolio.rb +291 -0
  14. data/lib/amq/client/async/adapters/event_machine.rb +392 -0
  15. data/lib/amq/client/async/adapters/eventmachine.rb +1 -0
  16. data/lib/amq/client/async/callbacks.rb +71 -0
  17. data/lib/amq/client/async/channel.rb +385 -0
  18. data/lib/amq/client/async/entity.rb +66 -0
  19. data/lib/amq/client/async/exchange.rb +157 -0
  20. data/lib/amq/client/async/extensions/rabbitmq/basic.rb +38 -0
  21. data/lib/amq/client/async/extensions/rabbitmq/confirm.rb +248 -0
  22. data/lib/amq/client/async/queue.rb +455 -0
  23. data/lib/amq/client/callbacks.rb +6 -65
  24. data/lib/amq/client/channel.rb +4 -376
  25. data/lib/amq/client/entity.rb +6 -57
  26. data/lib/amq/client/exchange.rb +4 -148
  27. data/lib/amq/client/extensions/rabbitmq/basic.rb +4 -28
  28. data/lib/amq/client/extensions/rabbitmq/confirm.rb +5 -240
  29. data/lib/amq/client/queue.rb +5 -450
  30. data/lib/amq/client/version.rb +1 -1
  31. data/spec/unit/client_spec.rb +10 -30
  32. metadata +16 -22
@@ -1,453 +1,8 @@
1
- # encoding: utf-8
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
- class Queue
11
-
12
- #
13
- # Behaviors
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
+