amqp 0.6.7 → 0.7.0.pre
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/.gitignore +6 -0
- data/CHANGELOG +5 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +16 -0
- data/README.md +145 -0
- data/Rakefile +5 -0
- data/amqp.gemspec +31 -79
- data/amqp.pre.gemspec +6 -0
- data/bin/irb +9 -0
- data/examples/mq/callbacks.rb +32 -0
- data/examples/mq/clock.rb +15 -6
- data/lib/amqp/buffer.rb +5 -5
- data/lib/amqp/client.rb +25 -1
- data/lib/amqp/frame.rb +1 -1
- data/lib/amqp/protocol.rb +1 -1
- data/lib/amqp/server.rb +1 -1
- data/lib/amqp/version.rb +1 -1
- data/lib/mq.rb +113 -82
- data/lib/mq/collection.rb +132 -0
- data/lib/mq/exchange.rb +70 -36
- data/lib/mq/queue.rb +53 -30
- data/spec/channel_close_spec.rb +13 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/sync_async_spec.rb +52 -0
- metadata +53 -22
- data/README +0 -128
data/lib/amqp/client.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path('../frame', __FILE__)
|
2
2
|
|
3
|
+
require 'uri'
|
4
|
+
|
3
5
|
module AMQP
|
4
6
|
class Error < StandardError; end
|
5
7
|
|
@@ -184,7 +186,15 @@ module AMQP
|
|
184
186
|
EM.reconnect @settings[:host], @settings[:port], self
|
185
187
|
end
|
186
188
|
|
187
|
-
def self.connect
|
189
|
+
def self.connect amqp_url_or_opts = nil
|
190
|
+
if amqp_url_or_opts.is_a?(String)
|
191
|
+
opts = parse_amqp_url(amqp_url_or_opts)
|
192
|
+
elsif amqp_url_or_opts.is_a?(Hash)
|
193
|
+
opts = amqp_url_or_opts
|
194
|
+
elsif amqp_url_or_opts.nil?
|
195
|
+
opts = Hash.new
|
196
|
+
end
|
197
|
+
|
188
198
|
opts = AMQP.settings.merge(opts)
|
189
199
|
EM.connect opts[:host], opts[:port], self, opts
|
190
200
|
end
|
@@ -206,5 +216,19 @@ module AMQP
|
|
206
216
|
pp args
|
207
217
|
puts
|
208
218
|
end
|
219
|
+
|
220
|
+
def self.parse_amqp_url(amqp_url)
|
221
|
+
uri = URI.parse(amqp_url)
|
222
|
+
raise("amqp:// uri required!") unless %w{amqp amqps}.include? uri.scheme
|
223
|
+
opts = {}
|
224
|
+
opts[:user] = URI.unescape(uri.user) if uri.user
|
225
|
+
opts[:pass] = URI.unescape(uri.password) if uri.password
|
226
|
+
opts[:vhost] = URI.unescape(uri.path) if uri.path
|
227
|
+
opts[:host] = uri.host if uri.host
|
228
|
+
opts[:port] = uri.port ? uri.port :
|
229
|
+
{"amqp"=>5672, "amqps"=>5671}[uri.scheme]
|
230
|
+
opts[:ssl] = uri.scheme == "amqps"
|
231
|
+
return opts
|
232
|
+
end
|
209
233
|
end
|
210
234
|
end
|
data/lib/amqp/frame.rb
CHANGED
data/lib/amqp/protocol.rb
CHANGED
data/lib/amqp/server.rb
CHANGED
data/lib/amqp/version.rb
CHANGED
data/lib/mq.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
$:.unshift File.expand_path(File.dirname(File.expand_path(__FILE__)))
|
5
5
|
require 'amqp'
|
6
|
+
require 'mq/collection'
|
6
7
|
|
7
8
|
class MQ
|
8
9
|
%w[ exchange queue rpc header ].each do |file|
|
@@ -32,7 +33,7 @@ end
|
|
32
33
|
# One consumer prints messages every second while the second consumer prints
|
33
34
|
# messages every 2 seconds. After 5 seconds has elapsed, the 1 second
|
34
35
|
# consumer is deleted.
|
35
|
-
#
|
36
|
+
#
|
36
37
|
# Of interest is the relationship of EventMachine to the process. All MQ
|
37
38
|
# operations must occur within the context of an EM.run block. We start
|
38
39
|
# EventMachine in its own thread with an empty block; all subsequent calls
|
@@ -44,39 +45,39 @@ end
|
|
44
45
|
#
|
45
46
|
# require 'rubygems'
|
46
47
|
# require 'mq'
|
47
|
-
#
|
48
|
+
#
|
48
49
|
# thr = Thread.new { EM.run }
|
49
|
-
#
|
50
|
+
#
|
50
51
|
# # turns on extreme logging
|
51
52
|
# #AMQP.logging = true
|
52
|
-
#
|
53
|
+
#
|
53
54
|
# def log *args
|
54
55
|
# p args
|
55
56
|
# end
|
56
|
-
#
|
57
|
+
#
|
57
58
|
# def publisher
|
58
59
|
# clock = MQ.fanout('clock')
|
59
60
|
# EM.add_periodic_timer(1) do
|
60
61
|
# puts
|
61
|
-
#
|
62
|
+
#
|
62
63
|
# log :publishing, time = Time.now
|
63
64
|
# clock.publish(Marshal.dump(time))
|
64
65
|
# end
|
65
66
|
# end
|
66
|
-
#
|
67
|
+
#
|
67
68
|
# def one_second_consumer
|
68
69
|
# MQ.queue('every second').bind(MQ.fanout('clock')).subscribe do |time|
|
69
70
|
# log 'every second', :received, Marshal.load(time)
|
70
71
|
# end
|
71
72
|
# end
|
72
|
-
#
|
73
|
+
#
|
73
74
|
# def two_second_consumer
|
74
75
|
# MQ.queue('every 2 seconds').bind('clock').subscribe do |time|
|
75
76
|
# time = Marshal.load(time)
|
76
77
|
# log 'every 2 seconds', :received, time if time.sec % 2 == 0
|
77
78
|
# end
|
78
79
|
# end
|
79
|
-
#
|
80
|
+
#
|
80
81
|
# def delete_one_second
|
81
82
|
# EM.add_timer(5) do
|
82
83
|
# # delete the 'every second' queue
|
@@ -84,33 +85,33 @@ end
|
|
84
85
|
# MQ.queue('every second').delete
|
85
86
|
# end
|
86
87
|
# end
|
87
|
-
#
|
88
|
+
#
|
88
89
|
# publisher
|
89
90
|
# one_second_consumer
|
90
91
|
# two_second_consumer
|
91
92
|
# delete_one_second
|
92
93
|
# thr.join
|
93
|
-
#
|
94
|
+
#
|
94
95
|
# __END__
|
95
|
-
#
|
96
|
+
#
|
96
97
|
# [:publishing, Tue Jan 06 22:46:14 -0600 2009]
|
97
98
|
# ["every second", :received, Tue Jan 06 22:46:14 -0600 2009]
|
98
99
|
# ["every 2 seconds", :received, Tue Jan 06 22:46:14 -0600 2009]
|
99
|
-
#
|
100
|
+
#
|
100
101
|
# [:publishing, Tue Jan 06 22:46:16 -0600 2009]
|
101
102
|
# ["every second", :received, Tue Jan 06 22:46:16 -0600 2009]
|
102
103
|
# ["every 2 seconds", :received, Tue Jan 06 22:46:16 -0600 2009]
|
103
|
-
#
|
104
|
+
#
|
104
105
|
# [:publishing, Tue Jan 06 22:46:17 -0600 2009]
|
105
106
|
# ["every second", :received, Tue Jan 06 22:46:17 -0600 2009]
|
106
|
-
#
|
107
|
+
#
|
107
108
|
# [:publishing, Tue Jan 06 22:46:18 -0600 2009]
|
108
109
|
# ["every second", :received, Tue Jan 06 22:46:18 -0600 2009]
|
109
110
|
# ["every 2 seconds", :received, Tue Jan 06 22:46:18 -0600 2009]
|
110
111
|
# ["Deleting [every second] queue"]
|
111
|
-
#
|
112
|
+
#
|
112
113
|
# [:publishing, Tue Jan 06 22:46:19 -0600 2009]
|
113
|
-
#
|
114
|
+
#
|
114
115
|
# [:publishing, Tue Jan 06 22:46:20 -0600 2009]
|
115
116
|
# ["every 2 seconds", :received, Tue Jan 06 22:46:20 -0600 2009]
|
116
117
|
#
|
@@ -146,9 +147,17 @@ class MQ
|
|
146
147
|
}
|
147
148
|
end
|
148
149
|
attr_reader :channel, :connection
|
149
|
-
|
150
|
+
|
151
|
+
def check_content_completion
|
152
|
+
if @body.length >= @header.size
|
153
|
+
@header.properties.update(@method.arguments)
|
154
|
+
@consumer.receive @header, @body if @consumer
|
155
|
+
@body = @header = @consumer = @method = nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
150
159
|
# May raise a MQ::Error exception when the frame payload contains a
|
151
|
-
# Protocol::Channel::Close object.
|
160
|
+
# Protocol::Channel::Close object.
|
152
161
|
#
|
153
162
|
# This usually occurs when a client attempts to perform an illegal
|
154
163
|
# operation. A short, and incomplete, list of potential illegal operations
|
@@ -163,14 +172,11 @@ class MQ
|
|
163
172
|
when Frame::Header
|
164
173
|
@header = frame.payload
|
165
174
|
@body = ''
|
175
|
+
check_content_completion
|
166
176
|
|
167
177
|
when Frame::Body
|
168
178
|
@body << frame.payload
|
169
|
-
|
170
|
-
@header.properties.update(@method.arguments)
|
171
|
-
@consumer.receive @header, @body if @consumer
|
172
|
-
@body = @header = @consumer = @method = nil
|
173
|
-
end
|
179
|
+
check_content_completion
|
174
180
|
|
175
181
|
when Frame::Method
|
176
182
|
case method = frame.payload
|
@@ -198,8 +204,26 @@ class MQ
|
|
198
204
|
MQ.error "Basic.CancelOk for invalid consumer tag: #{method.consumer_tag}"
|
199
205
|
end
|
200
206
|
|
207
|
+
when Protocol::Exchange::DeclareOk
|
208
|
+
# We can't use exchanges[method.exchange] because if the name would
|
209
|
+
# be an empty string, then AMQP broker generated a random one.
|
210
|
+
exchanges = self.exchanges.select { |exchange| exchange.opts[:nowait].eql?(false) }
|
211
|
+
exchange = exchanges.reverse.find { |exchange| exchange.status.eql?(:unfinished) }
|
212
|
+
exchange.receive_response method
|
213
|
+
|
201
214
|
when Protocol::Queue::DeclareOk
|
202
|
-
queues[
|
215
|
+
# We can't use queues[method.queue] because if the name would
|
216
|
+
# be an empty string, then AMQP broker generated a random one.
|
217
|
+
queues = self.queues.select { |queue| queue.opts[:nowait].eql?(false) }
|
218
|
+
queue = queues.reverse.find { |queue| queue.status.eql?(:unfinished) }
|
219
|
+
queue.receive_status method
|
220
|
+
|
221
|
+
when Protocol::Queue::BindOk
|
222
|
+
# We can't use queues[method.queue] because if the name would
|
223
|
+
# be an empty string, then AMQP broker generated a random one.
|
224
|
+
queues = self.queues.select { |queue| queue.opts[:nowait].eql?(false) }
|
225
|
+
queue = queues.reverse.find { |queue| queue.status.eql?(:unbound) }
|
226
|
+
queue.after_bind method
|
203
227
|
|
204
228
|
when Protocol::Basic::Deliver, Protocol::Basic::GetOk
|
205
229
|
@method = method
|
@@ -225,6 +249,8 @@ class MQ
|
|
225
249
|
raise Error, "#{method.reply_text} in #{Protocol.classes[method.class_id].methods[method.method_id]} on #{@channel}"
|
226
250
|
|
227
251
|
when Protocol::Channel::CloseOk
|
252
|
+
@on_close && @on_close.call(self)
|
253
|
+
|
228
254
|
@closing = false
|
229
255
|
conn.callback{ |c|
|
230
256
|
c.channels.delete @channel
|
@@ -259,8 +285,8 @@ class MQ
|
|
259
285
|
# == Direct
|
260
286
|
# A direct exchange is useful for 1:1 communication between a publisher and
|
261
287
|
# subscriber. Messages are routed to the queue with a binding that shares
|
262
|
-
# the same name as the exchange. Alternately, the messages are routed to
|
263
|
-
# the bound queue that shares the same name as the routing key used for
|
288
|
+
# the same name as the exchange. Alternately, the messages are routed to
|
289
|
+
# the bound queue that shares the same name as the routing key used for
|
264
290
|
# defining the exchange. This exchange type does not honor the +:key+ option
|
265
291
|
# when defining a new instance with a name. It _will_ honor the +:key+ option
|
266
292
|
# if the exchange name is the empty string.
|
@@ -287,19 +313,19 @@ class MQ
|
|
287
313
|
# If set, the server will not create the exchange if it does not
|
288
314
|
# already exist. The client can use this to check whether an exchange
|
289
315
|
# exists without modifying the server state.
|
290
|
-
#
|
316
|
+
#
|
291
317
|
# * :durable => true | false (default false)
|
292
318
|
# If set when creating a new exchange, the exchange will be marked as
|
293
319
|
# durable. Durable exchanges remain active when a server restarts.
|
294
320
|
# Non-durable exchanges (transient exchanges) are purged if/when a
|
295
|
-
# server restarts.
|
321
|
+
# server restarts.
|
296
322
|
#
|
297
323
|
# A transient exchange (the default) is stored in memory-only. The
|
298
324
|
# exchange and all bindings will be lost on a server restart.
|
299
325
|
# It makes no sense to publish a persistent message to a transient
|
300
326
|
# exchange.
|
301
327
|
#
|
302
|
-
# Durable exchanges and their bindings are recreated upon a server
|
328
|
+
# Durable exchanges and their bindings are recreated upon a server
|
303
329
|
# restart. Any published messages not routed to a bound queue are lost.
|
304
330
|
#
|
305
331
|
# * :auto_delete => true | false (default false)
|
@@ -326,25 +352,25 @@ class MQ
|
|
326
352
|
# * redeclare an already-declared exchange to a different type
|
327
353
|
# * :passive => true and the exchange does not exist (NOT_FOUND)
|
328
354
|
#
|
329
|
-
def direct name = 'amq.direct', opts = {}
|
330
|
-
exchanges
|
355
|
+
def direct name = 'amq.direct', opts = {}, &block
|
356
|
+
self.exchanges << Exchange.new(self, :direct, name, opts, &block)
|
331
357
|
end
|
332
358
|
|
333
359
|
# Defines, intializes and returns an Exchange to act as an ingress
|
334
360
|
# point for all published messages.
|
335
361
|
#
|
336
362
|
# == Fanout
|
337
|
-
# A fanout exchange is useful for 1:N communication where one publisher
|
338
|
-
# feeds multiple subscribers. Like direct exchanges, messages published
|
339
|
-
# to a fanout exchange are delivered to queues whose name matches the
|
340
|
-
# exchange name (or are bound to that exchange name). Each queue gets
|
363
|
+
# A fanout exchange is useful for 1:N communication where one publisher
|
364
|
+
# feeds multiple subscribers. Like direct exchanges, messages published
|
365
|
+
# to a fanout exchange are delivered to queues whose name matches the
|
366
|
+
# exchange name (or are bound to that exchange name). Each queue gets
|
341
367
|
# its own copy of the message.
|
342
368
|
#
|
343
369
|
# Any published message, regardless of its persistence setting, is thrown
|
344
370
|
# away by the exchange when there are no queues bound to it.
|
345
371
|
#
|
346
|
-
# Like the direct exchange type, this exchange type does not honor the
|
347
|
-
# +:key+ option when defining a new instance with a name. It _will_ honor
|
372
|
+
# Like the direct exchange type, this exchange type does not honor the
|
373
|
+
# +:key+ option when defining a new instance with a name. It _will_ honor
|
348
374
|
# the +:key+ option if the exchange name is the empty string.
|
349
375
|
# Allocating this exchange without a name _or_ with the empty string
|
350
376
|
# will use the internal 'amq.fanout' exchange.
|
@@ -373,19 +399,19 @@ class MQ
|
|
373
399
|
# If set, the server will not create the exchange if it does not
|
374
400
|
# already exist. The client can use this to check whether an exchange
|
375
401
|
# exists without modifying the server state.
|
376
|
-
#
|
402
|
+
#
|
377
403
|
# * :durable => true | false (default false)
|
378
404
|
# If set when creating a new exchange, the exchange will be marked as
|
379
405
|
# durable. Durable exchanges remain active when a server restarts.
|
380
406
|
# Non-durable exchanges (transient exchanges) are purged if/when a
|
381
|
-
# server restarts.
|
407
|
+
# server restarts.
|
382
408
|
#
|
383
409
|
# A transient exchange (the default) is stored in memory-only. The
|
384
410
|
# exchange and all bindings will be lost on a server restart.
|
385
411
|
# It makes no sense to publish a persistent message to a transient
|
386
412
|
# exchange.
|
387
413
|
#
|
388
|
-
# Durable exchanges and their bindings are recreated upon a server
|
414
|
+
# Durable exchanges and their bindings are recreated upon a server
|
389
415
|
# restart. Any published messages not routed to a bound queue are lost.
|
390
416
|
#
|
391
417
|
# * :auto_delete => true | false (default false)
|
@@ -412,18 +438,18 @@ class MQ
|
|
412
438
|
# * redeclare an already-declared exchange to a different type
|
413
439
|
# * :passive => true and the exchange does not exist (NOT_FOUND)
|
414
440
|
#
|
415
|
-
def fanout name = 'amq.fanout', opts = {}
|
416
|
-
exchanges
|
441
|
+
def fanout name = 'amq.fanout', opts = {}, &block
|
442
|
+
self.exchanges << Exchange.new(self, :fanout, name, opts, &block)
|
417
443
|
end
|
418
444
|
|
419
445
|
# Defines, intializes and returns an Exchange to act as an ingress
|
420
446
|
# point for all published messages.
|
421
447
|
#
|
422
448
|
# == Topic
|
423
|
-
# A topic exchange allows for messages to be published to an exchange
|
449
|
+
# A topic exchange allows for messages to be published to an exchange
|
424
450
|
# tagged with a specific routing key. The Exchange uses the routing key
|
425
|
-
# to determine which queues to deliver the message. Wildcard matching
|
426
|
-
# is allowed. The topic must be declared using dot notation to separate
|
451
|
+
# to determine which queues to deliver the message. Wildcard matching
|
452
|
+
# is allowed. The topic must be declared using dot notation to separate
|
427
453
|
# each subtopic.
|
428
454
|
#
|
429
455
|
# This is the only exchange type to honor the +key+ hash key for all
|
@@ -432,14 +458,14 @@ class MQ
|
|
432
458
|
# Any published message, regardless of its persistence setting, is thrown
|
433
459
|
# away by the exchange when there are no queues bound to it.
|
434
460
|
#
|
435
|
-
# As part of the AMQP standard, each server _should_ predeclare a topic
|
461
|
+
# As part of the AMQP standard, each server _should_ predeclare a topic
|
436
462
|
# exchange called 'amq.topic' (this is not required by the standard).
|
437
463
|
# Allocating this exchange without a name _or_ with the empty string
|
438
464
|
# will use the internal 'amq.topic' exchange.
|
439
465
|
#
|
440
466
|
# The classic example is delivering market data. When publishing market
|
441
|
-
# data for stocks, we may subdivide the stream based on 2
|
442
|
-
# characteristics: nation code and trading symbol. The topic tree for
|
467
|
+
# data for stocks, we may subdivide the stream based on 2
|
468
|
+
# characteristics: nation code and trading symbol. The topic tree for
|
443
469
|
# Apple Computer would look like:
|
444
470
|
# 'stock.us.aapl'
|
445
471
|
# For a foreign stock, it may look like:
|
@@ -474,10 +500,10 @@ class MQ
|
|
474
500
|
# end
|
475
501
|
# end
|
476
502
|
#
|
477
|
-
# For matching, the '*' (asterisk) wildcard matches against one
|
478
|
-
# dot-separated item only. The '#' wildcard (hash or pound symbol)
|
479
|
-
# matches against 0 or more dot-separated items. If none of these
|
480
|
-
# symbols are used, the exchange performs a comparison looking for an
|
503
|
+
# For matching, the '*' (asterisk) wildcard matches against one
|
504
|
+
# dot-separated item only. The '#' wildcard (hash or pound symbol)
|
505
|
+
# matches against 0 or more dot-separated items. If none of these
|
506
|
+
# symbols are used, the exchange performs a comparison looking for an
|
481
507
|
# exact match.
|
482
508
|
#
|
483
509
|
# == Options
|
@@ -485,19 +511,19 @@ class MQ
|
|
485
511
|
# If set, the server will not create the exchange if it does not
|
486
512
|
# already exist. The client can use this to check whether an exchange
|
487
513
|
# exists without modifying the server state.
|
488
|
-
#
|
514
|
+
#
|
489
515
|
# * :durable => true | false (default false)
|
490
516
|
# If set when creating a new exchange, the exchange will be marked as
|
491
517
|
# durable. Durable exchanges remain active when a server restarts.
|
492
518
|
# Non-durable exchanges (transient exchanges) are purged if/when a
|
493
|
-
# server restarts.
|
519
|
+
# server restarts.
|
494
520
|
#
|
495
521
|
# A transient exchange (the default) is stored in memory-only. The
|
496
522
|
# exchange and all bindings will be lost on a server restart.
|
497
523
|
# It makes no sense to publish a persistent message to a transient
|
498
524
|
# exchange.
|
499
525
|
#
|
500
|
-
# Durable exchanges and their bindings are recreated upon a server
|
526
|
+
# Durable exchanges and their bindings are recreated upon a server
|
501
527
|
# restart. Any published messages not routed to a bound queue are lost.
|
502
528
|
#
|
503
529
|
# * :auto_delete => true | false (default false)
|
@@ -524,25 +550,25 @@ class MQ
|
|
524
550
|
# * redeclare an already-declared exchange to a different type
|
525
551
|
# * :passive => true and the exchange does not exist (NOT_FOUND)
|
526
552
|
#
|
527
|
-
def topic name = 'amq.topic', opts = {}
|
528
|
-
exchanges
|
553
|
+
def topic name = 'amq.topic', opts = {}, &block
|
554
|
+
self.exchanges << Exchange.new(self, :topic, name, opts, &block)
|
529
555
|
end
|
530
556
|
|
531
557
|
# Defines, intializes and returns an Exchange to act as an ingress
|
532
558
|
# point for all published messages.
|
533
559
|
#
|
534
560
|
# == Headers
|
535
|
-
# A headers exchange allows for messages to be published to an exchange
|
561
|
+
# A headers exchange allows for messages to be published to an exchange
|
536
562
|
#
|
537
563
|
# Any published message, regardless of its persistence setting, is thrown
|
538
564
|
# away by the exchange when there are no queues bound to it.
|
539
565
|
#
|
540
|
-
# As part of the AMQP standard, each server _should_ predeclare a headers
|
566
|
+
# As part of the AMQP standard, each server _should_ predeclare a headers
|
541
567
|
# exchange called 'amq.match' (this is not required by the standard).
|
542
568
|
# Allocating this exchange without a name _or_ with the empty string
|
543
569
|
# will use the internal 'amq.match' exchange.
|
544
570
|
#
|
545
|
-
# TODO: The classic example is ...
|
571
|
+
# TODO: The classic example is ...
|
546
572
|
#
|
547
573
|
# When publishing data to the exchange, bound queues subscribing to the
|
548
574
|
# exchange indicate which data interests them by passing arguments
|
@@ -551,8 +577,8 @@ class MQ
|
|
551
577
|
# may be 'any' or 'all'. If unspecified (in RabbitMQ at least), it defaults
|
552
578
|
# to "all".
|
553
579
|
#
|
554
|
-
# A value of 'all' for 'x-match' implies that all values must match (i.e.
|
555
|
-
# it does an AND of the headers ), while a value of 'any' implies that
|
580
|
+
# A value of 'all' for 'x-match' implies that all values must match (i.e.
|
581
|
+
# it does an AND of the headers ), while a value of 'any' implies that
|
556
582
|
# at least one should match (ie. it does an OR).
|
557
583
|
#
|
558
584
|
# TODO: document behavior when either the binding or the message is missing
|
@@ -565,19 +591,19 @@ class MQ
|
|
565
591
|
# If set, the server will not create the exchange if it does not
|
566
592
|
# already exist. The client can use this to check whether an exchange
|
567
593
|
# exists without modifying the server state.
|
568
|
-
#
|
594
|
+
#
|
569
595
|
# * :durable => true | false (default false)
|
570
596
|
# If set when creating a new exchange, the exchange will be marked as
|
571
597
|
# durable. Durable exchanges remain active when a server restarts.
|
572
598
|
# Non-durable exchanges (transient exchanges) are purged if/when a
|
573
|
-
# server restarts.
|
599
|
+
# server restarts.
|
574
600
|
#
|
575
601
|
# A transient exchange (the default) is stored in memory-only. The
|
576
602
|
# exchange and all bindings will be lost on a server restart.
|
577
603
|
# It makes no sense to publish a persistent message to a transient
|
578
604
|
# exchange.
|
579
605
|
#
|
580
|
-
# Durable exchanges and their bindings are recreated upon a server
|
606
|
+
# Durable exchanges and their bindings are recreated upon a server
|
581
607
|
# restart. Any published messages not routed to a bound queue are lost.
|
582
608
|
#
|
583
609
|
# * :auto_delete => true | false (default false)
|
@@ -604,8 +630,8 @@ class MQ
|
|
604
630
|
# * redeclare an already-declared exchange to a different type
|
605
631
|
# * :passive => true and the exchange does not exist (NOT_FOUND)
|
606
632
|
# * using a value other than "any" or "all" for "x-match"
|
607
|
-
def headers name = 'amq.match', opts = {}
|
608
|
-
exchanges
|
633
|
+
def headers name = 'amq.match', opts = {}, &block
|
634
|
+
self.exchanges << Exchange.new(self, :headers, name, opts, &block)
|
609
635
|
end
|
610
636
|
|
611
637
|
# Queues store and forward messages. Queues can be configured in the server
|
@@ -624,7 +650,7 @@ class MQ
|
|
624
650
|
# If set, the server will not create the exchange if it does not
|
625
651
|
# already exist. The client can use this to check whether an exchange
|
626
652
|
# exists without modifying the server state.
|
627
|
-
#
|
653
|
+
#
|
628
654
|
# * :durable => true | false (default false)
|
629
655
|
# If set when creating a new queue, the queue will be marked as
|
630
656
|
# durable. Durable queues remain active when a server restarts.
|
@@ -657,7 +683,7 @@ class MQ
|
|
657
683
|
# If set, the queue is deleted when all consumers have finished
|
658
684
|
# using it. Last consumer can be cancelled either explicitly or because
|
659
685
|
# its channel is closed. If there was no consumer ever on the queue, it
|
660
|
-
# won't be deleted.
|
686
|
+
# won't be deleted.
|
661
687
|
#
|
662
688
|
# The server waits for a short period of time before
|
663
689
|
# determining the queue is unused to give time to the client code
|
@@ -674,8 +700,12 @@ class MQ
|
|
674
700
|
# not wait for a reply method. If the server could not complete the
|
675
701
|
# method it will raise a channel or connection exception.
|
676
702
|
#
|
677
|
-
def queue name, opts = {}
|
678
|
-
queues
|
703
|
+
def queue name, opts = {}, &block
|
704
|
+
self.queues << Queue.new(self, name, opts, &block)
|
705
|
+
end
|
706
|
+
|
707
|
+
def queue! name, opts = {}, &block
|
708
|
+
self.queues.add! Queue.new(self, name, opts, &block)
|
679
709
|
end
|
680
710
|
|
681
711
|
# Takes a channel, queue and optional object.
|
@@ -687,14 +717,14 @@ class MQ
|
|
687
717
|
#
|
688
718
|
# Marshalling and unmarshalling the objects is handled internally. This
|
689
719
|
# marshalling is subject to the same restrictions as defined in the
|
690
|
-
# Marshal[http://ruby-doc.org/core/classes/Marshal.html] standard
|
720
|
+
# Marshal[http://ruby-doc.org/core/classes/Marshal.html] standard
|
691
721
|
# library. See that documentation for further reference.
|
692
722
|
#
|
693
|
-
# When the optional object is not passed, the returned rpc reference is
|
694
|
-
# used to send messages and arguments to the queue. See #method_missing
|
695
|
-
# which does all of the heavy lifting with the proxy. Some client
|
696
|
-
# elsewhere must call this method *with* the optional block so that
|
697
|
-
# there is a valid destination. Failure to do so will just enqueue
|
723
|
+
# When the optional object is not passed, the returned rpc reference is
|
724
|
+
# used to send messages and arguments to the queue. See #method_missing
|
725
|
+
# which does all of the heavy lifting with the proxy. Some client
|
726
|
+
# elsewhere must call this method *with* the optional block so that
|
727
|
+
# there is a valid destination. Failure to do so will just enqueue
|
698
728
|
# marshalled messages that are never consumed.
|
699
729
|
#
|
700
730
|
# EM.run do
|
@@ -718,7 +748,8 @@ class MQ
|
|
718
748
|
rpcs[name] ||= RPC.new(self, name, obj)
|
719
749
|
end
|
720
750
|
|
721
|
-
def close
|
751
|
+
def close(&block)
|
752
|
+
@on_close = block
|
722
753
|
if @deferred_status == :succeeded
|
723
754
|
send Protocol::Channel::Close.new(:reply_code => 200,
|
724
755
|
:reply_text => 'bye',
|
@@ -762,14 +793,14 @@ class MQ
|
|
762
793
|
#
|
763
794
|
# Not typically called by client code.
|
764
795
|
def exchanges
|
765
|
-
@exchanges ||=
|
796
|
+
@exchanges ||= MQ::Collection.new
|
766
797
|
end
|
767
798
|
|
768
799
|
# Returns a hash of all the queue proxy objects.
|
769
800
|
#
|
770
801
|
# Not typically called by client code.
|
771
802
|
def queues
|
772
|
-
@queues ||=
|
803
|
+
@queues ||= MQ::Collection.new
|
773
804
|
end
|
774
805
|
|
775
806
|
def get_queue
|
@@ -844,4 +875,4 @@ class MQ
|
|
844
875
|
def MQ.id
|
845
876
|
Thread.current[:mq_id] ||= "#{`hostname`.strip}-#{Process.pid}-#{Thread.current.object_id}"
|
846
877
|
end
|
847
|
-
end
|
878
|
+
end
|