amqp 1.0.0.pre2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/README.md +80 -72
- data/amqp.gemspec +5 -13
- data/docs/08Migration.textile +4 -0
- data/docs/AMQP091ModelExplained.textile +6 -1
- data/docs/Bindings.textile +4 -0
- data/docs/Clustering.textile +4 -0
- data/docs/ConnectingToTheBroker.textile +4 -0
- data/docs/ConnectionEncryptionWithTLS.textile +4 -0
- data/docs/DocumentationGuidesIndex.textile +4 -0
- data/docs/Durability.textile +4 -0
- data/docs/ErrorHandling.textile +4 -0
- data/docs/Exchanges.textile +4 -0
- data/docs/GettingStarted.textile +4 -0
- data/docs/PatternsAndUseCases.textile +4 -1
- data/docs/Queues.textile +4 -0
- data/docs/RabbitMQVersions.textile +4 -0
- data/docs/RunningTests.textile +4 -0
- data/docs/TestingWithEventedSpec.textile +4 -0
- data/docs/Troubleshooting.textile +4 -0
- data/docs/VendorSpecificExtensions.textile +4 -0
- data/examples/error_handling/automatic_recovery_of_channel_and_queues.rb +1 -1
- data/examples/error_handling/automatically_recovering_hello_world_consumer.rb +1 -1
- data/examples/error_handling/automatically_recovering_hello_world_consumer_that_uses_a_server_named_queue.rb +1 -1
- data/examples/error_handling/connection_level_exception.rb +1 -1
- data/examples/error_handling/connection_level_exception_with_objects.rb +1 -1
- data/examples/error_handling/connection_loss_handler.rb +4 -3
- data/examples/error_handling/hello_world_producer.rb +1 -1
- data/examples/error_handling/manual_connection_and_channel_recovery.rb +1 -1
- data/examples/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +1 -1
- data/examples/extensions/rabbitmq/using_alternate_exchanges.rb +1 -1
- data/examples/guides/getting_started/01_hello_world.rb +1 -1
- data/examples/guides/getting_started/02_hello_world_dslified.rb +1 -1
- data/examples/hello_world.rb +1 -1
- data/examples/hello_world_with_an_empty_string.rb +1 -1
- data/examples/hello_world_with_eventmachine_in_a_separate_thread.rb +2 -2
- data/examples/hello_world_with_large_payload.rb +41 -41
- data/examples/patterns/request_reply/client.rb +1 -2
- data/examples/patterns/request_reply/server.rb +0 -1
- data/examples/publishing/returned_messages.rb +1 -1
- data/examples/queues/accessing_message_metadata.rb +1 -1
- data/examples/queues/cancel_default_consumer.rb +1 -1
- data/lib/amqp/channel.rb +34 -16
- data/lib/amqp/client.rb +2 -2
- data/lib/amqp/connection.rb +2 -1
- data/lib/amqp/consumer.rb +2 -2
- data/lib/amqp/exceptions.rb +11 -2
- data/lib/amqp/exchange.rb +5 -5
- data/lib/amqp/queue.rb +51 -26
- data/lib/amqp/session.rb +5 -5
- data/lib/amqp/version.rb +1 -1
- data/spec/integration/basic_get_spec.rb +82 -27
- data/spec/integration/basic_return_spec.rb +3 -3
- data/spec/integration/channel_level_exception_with_multiple_channels_spec.rb +0 -1
- data/spec/integration/exchange_declaration_spec.rb +71 -102
- data/spec/integration/extensions/rabbitmq/publisher_confirmations_spec.rb +1 -1
- data/spec/integration/fanout_exchange_routing_spec.rb +1 -1
- data/spec/integration/multiple_consumers_per_queue_spec.rb +3 -160
- data/spec/integration/queue_redeclaration_with_incompatible_attributes_spec.rb +25 -12
- data/spec/integration/regressions/concurrent_publishing_on_the_same_channel_spec.rb +1 -1
- data/spec/integration/remove_individual_binding_spec.rb +51 -0
- data/spec/integration/reply_queue_communication_spec.rb +1 -2
- data/spec/integration/store_and_forward_spec.rb +6 -9
- data/spec/integration/topic_subscription_spec.rb +5 -4
- data/spec/spec_helper.rb +8 -2
- data/spec/unit/amqp/connection_spec.rb +3 -1
- metadata +93 -109
- data/spec/integration/immediate_messages_spec.rb +0 -59
data/lib/amqp/client.rb
CHANGED
@@ -22,7 +22,7 @@ module AMQP
|
|
22
22
|
# @see AMQP.connect
|
23
23
|
# @api plugin
|
24
24
|
#
|
25
|
-
# @see http://
|
25
|
+
# @see http://rubyamqp.info/articles/connecting_to_broker/ Connecting to The Broker documentation guide
|
26
26
|
def self.connect(connection_string_or_options = {}, options = {}, &block)
|
27
27
|
opts = case connection_string_or_options
|
28
28
|
when String then
|
@@ -82,7 +82,7 @@ module AMQP
|
|
82
82
|
#
|
83
83
|
# @raise [ArgumentError] When connection URI schema is not amqp or amqps, or the path contains multiple segments
|
84
84
|
#
|
85
|
-
# @see http://
|
85
|
+
# @see http://rubyamqp.info/articles/connecting_to_broker/ Connecting to The Broker documentation guide
|
86
86
|
# @api public
|
87
87
|
def self.parse_connection_uri(connection_string)
|
88
88
|
AMQ::Client::Settings.parse_amqp_url(connection_string)
|
data/lib/amqp/connection.rb
CHANGED
@@ -54,7 +54,7 @@ module AMQP
|
|
54
54
|
# Pass it a block if you want a piece of code to be run once default connection
|
55
55
|
# is successfully closed.
|
56
56
|
#
|
57
|
-
# @note If default connection was never
|
57
|
+
# @note If default connection was never established or is in the closing state already,
|
58
58
|
# this method has no effect.
|
59
59
|
# @api public
|
60
60
|
def self.stop(reply_code = 200, reply_text = "Goodbye", &block)
|
@@ -192,6 +192,7 @@ module AMQP
|
|
192
192
|
# @option connection_options_or_string [String] :username ("guest") Username to use. Also can be specified as :user.
|
193
193
|
# @option connection_options_or_string [String] :password ("guest") Password to use. Also can be specified as :pass.
|
194
194
|
# @option connection_options_or_string [Hash] :ssl TLS (SSL) parameters to use.
|
195
|
+
# @option connection_options_or_string [Fixnum] :heartbeat (0) Connection heartbeat, in seconds. 0 means no heartbeat. Can also be configured server-side starting with RabbitMQ 3.0.
|
195
196
|
# @option connection_options_or_string [#call] :on_tcp_connection_failure A callable object that will be run if connection to server fails
|
196
197
|
# @option connection_options_or_string [#call] :on_possible_authentication_failure A callable object that will be run if authentication fails (see Authentication failure section)
|
197
198
|
#
|
data/lib/amqp/consumer.rb
CHANGED
@@ -139,7 +139,7 @@ module AMQP
|
|
139
139
|
# @return [Consumer] self
|
140
140
|
#
|
141
141
|
# @api public
|
142
|
-
# @see http://
|
142
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Reference.pdf AMQP 0.9.1 protocol documentation (Section 1.8.3.13.)
|
143
143
|
def acknowledge(delivery_tag)
|
144
144
|
super(delivery_tag)
|
145
145
|
end # acknowledge(delivery_tag)
|
@@ -148,7 +148,7 @@ module AMQP
|
|
148
148
|
# @return [Consumer] self
|
149
149
|
#
|
150
150
|
# @api public
|
151
|
-
# @see http://
|
151
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Reference.pdf AMQP 0.9.1 protocol documentation (Section 1.8.3.14.)
|
152
152
|
def reject(delivery_tag, requeue = true)
|
153
153
|
super(delivery_tag, requeue)
|
154
154
|
end # reject(delivery_tag, requeue = true)
|
data/lib/amqp/exceptions.rb
CHANGED
@@ -30,7 +30,7 @@ module AMQP
|
|
30
30
|
@settings = settings
|
31
31
|
@cause = cause
|
32
32
|
|
33
|
-
super("Could not
|
33
|
+
super("Could not establish TCP connection to #{@settings[:host]}:#{@settings[:port]}")
|
34
34
|
end # TCPConnectionFailed
|
35
35
|
end
|
36
36
|
|
@@ -43,8 +43,17 @@ module AMQP
|
|
43
43
|
def initialize(settings)
|
44
44
|
@settings = settings
|
45
45
|
|
46
|
-
super("AMQP broker closed TCP connection before authentication succeeded: this usually means authentication failure due to misconfiguration. Settings are #{
|
46
|
+
super("AMQP broker closed TCP connection before authentication succeeded: this usually means authentication failure due to misconfiguration. Settings are #{filtered_settings.inspect}")
|
47
47
|
end # initialize(settings)
|
48
|
+
|
49
|
+
def filtered_settings
|
50
|
+
filtered_settings = settings.dup
|
51
|
+
[:pass, :password].each do |sensitve_setting|
|
52
|
+
filtered_settings[sensitve_setting] &&= '[filtered]'
|
53
|
+
end
|
54
|
+
|
55
|
+
filtered_settings
|
56
|
+
end
|
48
57
|
end # PossibleAuthenticationFailureError
|
49
58
|
|
50
59
|
|
data/lib/amqp/exchange.rb
CHANGED
@@ -134,9 +134,9 @@ module AMQP
|
|
134
134
|
# @see Channel#topic
|
135
135
|
# @see Channel#headers
|
136
136
|
# @see Queue
|
137
|
-
# @see http://
|
138
|
-
# @see http://
|
139
|
-
# @see http://
|
137
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 2.1.1)
|
138
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 2.1.5)
|
139
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 3.1.3)
|
140
140
|
class Exchange < AMQ::Client::Exchange
|
141
141
|
|
142
142
|
#
|
@@ -162,7 +162,7 @@ module AMQP
|
|
162
162
|
# AMQP::Exchange.default(channel).publish("make clean", routing_key => "tasks")
|
163
163
|
#
|
164
164
|
# @see Exchange
|
165
|
-
# @see http://
|
165
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 2.1.2.4)
|
166
166
|
# @note Do not confuse default exchange with amq.direct: amq.direct is a pre-defined direct
|
167
167
|
# exchange that doesn't have any special routing semantics.
|
168
168
|
# @return [Exchange] An instance that corresponds to the default exchange (of type direct).
|
@@ -292,7 +292,7 @@ module AMQP
|
|
292
292
|
# @see Channel#topic
|
293
293
|
# @see Channel#headers
|
294
294
|
# @see Queue
|
295
|
-
# @see http://
|
295
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 3.1.3)
|
296
296
|
#
|
297
297
|
# @return [Exchange]
|
298
298
|
# @api public
|
data/lib/amqp/queue.rb
CHANGED
@@ -97,7 +97,7 @@ module AMQP
|
|
97
97
|
#
|
98
98
|
# h2. Queue durability and persistence of messages.
|
99
99
|
#
|
100
|
-
# Learn more in our {
|
100
|
+
# Learn more in our {http://rubyamqp.info/articles/durability/}.
|
101
101
|
#
|
102
102
|
#
|
103
103
|
# h2. Message ordering
|
@@ -112,11 +112,11 @@ module AMQP
|
|
112
112
|
# Learn more in {file:docs/ErrorHandling.textile Error Handling guide}.
|
113
113
|
#
|
114
114
|
#
|
115
|
-
# @note Please make sure you read {
|
115
|
+
# @note Please make sure you read {http://rubyamqp.info/articles/durability/} that covers exchanges durability vs. messages
|
116
116
|
# persistence.
|
117
117
|
#
|
118
118
|
#
|
119
|
-
# @see http://
|
119
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification (Section 2.1.1)
|
120
120
|
# @see AMQP::Exchange
|
121
121
|
class Queue < AMQ::Client::Queue
|
122
122
|
|
@@ -221,7 +221,11 @@ module AMQP
|
|
221
221
|
#
|
222
222
|
# @api public
|
223
223
|
def once_declared(&block)
|
224
|
-
@declaration_deferrable.callback
|
224
|
+
@declaration_deferrable.callback do
|
225
|
+
# guards against cases when deferred operations
|
226
|
+
# don't complete before the channel is closed
|
227
|
+
block.call if @channel.open?
|
228
|
+
end
|
225
229
|
end # once_declared(&block)
|
226
230
|
|
227
231
|
|
@@ -281,14 +285,8 @@ module AMQP
|
|
281
285
|
# @api public
|
282
286
|
# @see Queue#unbind
|
283
287
|
def bind(exchange, opts = {}, &block)
|
284
|
-
|
285
|
-
|
286
|
-
@declaration_deferrable.callback do
|
287
|
-
super(exchange, (opts[:key] || opts[:routing_key] || AMQ::Protocol::EMPTY_STRING), (opts[:nowait] || block.nil?), opts[:arguments], &block)
|
288
|
-
end
|
289
|
-
end
|
290
|
-
else
|
291
|
-
@channel.once_open do
|
288
|
+
@channel.once_open do
|
289
|
+
self.once_name_is_available do
|
292
290
|
super(exchange, (opts[:key] || opts[:routing_key] || AMQ::Protocol::EMPTY_STRING), (opts[:nowait] || block.nil?), opts[:arguments], &block)
|
293
291
|
end
|
294
292
|
end
|
@@ -345,7 +343,8 @@ module AMQP
|
|
345
343
|
# {Queue#subscribe} or {Queue#pop} call.
|
346
344
|
#
|
347
345
|
# @param [Exchange] Exchange to unbind from.
|
348
|
-
#
|
346
|
+
# @option opts [String] :routing_key Binding routing key
|
347
|
+
# @option opts [Hash] :arguments Binding arguments
|
349
348
|
# @option opts [Boolean] :nowait (true) If set, the server will not respond to the method. The client should
|
350
349
|
# not wait for a reply method. If the server could not complete the
|
351
350
|
# method it will raise a channel or connection exception.
|
@@ -357,7 +356,9 @@ module AMQP
|
|
357
356
|
# @see Queue#bind
|
358
357
|
def unbind(exchange, opts = {}, &block)
|
359
358
|
@channel.once_open do
|
360
|
-
|
359
|
+
self.once_name_is_available do
|
360
|
+
super(exchange, (opts[:key] || opts[:routing_key] || AMQ::Protocol::EMPTY_STRING), opts[:arguments], &block)
|
361
|
+
end
|
361
362
|
end
|
362
363
|
end
|
363
364
|
|
@@ -391,7 +392,9 @@ module AMQP
|
|
391
392
|
# @see Queue#unbind
|
392
393
|
def delete(opts = {}, &block)
|
393
394
|
@channel.once_open do
|
394
|
-
|
395
|
+
self.once_name_is_available do
|
396
|
+
super(opts.fetch(:if_unused, false), opts.fetch(:if_empty, false), opts.fetch(:nowait, false), &block)
|
397
|
+
end
|
395
398
|
end
|
396
399
|
|
397
400
|
# backwards compatibility
|
@@ -416,7 +419,9 @@ module AMQP
|
|
416
419
|
# @see Queue#unbind
|
417
420
|
def purge(opts = {}, &block)
|
418
421
|
@channel.once_open do
|
419
|
-
|
422
|
+
self.once_declared do
|
423
|
+
super(opts.fetch(:nowait, false), &block)
|
424
|
+
end
|
420
425
|
end
|
421
426
|
|
422
427
|
# backwards compatibility
|
@@ -477,11 +482,17 @@ module AMQP
|
|
477
482
|
}
|
478
483
|
|
479
484
|
@channel.once_open do
|
480
|
-
|
481
|
-
|
485
|
+
self.once_name_is_available do
|
486
|
+
# see AMQ::Client::Queue#get in amq-client
|
487
|
+
self.get(!opts.fetch(:ack, false), &shim)
|
488
|
+
end
|
482
489
|
end
|
483
490
|
else
|
484
|
-
@channel.once_open
|
491
|
+
@channel.once_open do
|
492
|
+
self.once_name_is_available do
|
493
|
+
self.get(!opts.fetch(:ack, false))
|
494
|
+
end
|
495
|
+
end
|
485
496
|
end
|
486
497
|
end
|
487
498
|
|
@@ -719,7 +730,9 @@ module AMQP
|
|
719
730
|
opts[:nowait] = false if (@on_confirm_subscribe = opts[:confirm])
|
720
731
|
|
721
732
|
@channel.once_open do
|
722
|
-
self.
|
733
|
+
self.once_name_is_available do
|
734
|
+
# guards against a pathological case race condition when a channel
|
735
|
+
# is opened and closed before delayed operations are completed.
|
723
736
|
self.consume(!opts[:ack], opts[:exclusive], (opts[:nowait] || block.nil?), opts[:no_local], nil, &opts[:confirm])
|
724
737
|
|
725
738
|
self.on_delivery(&block)
|
@@ -785,7 +798,7 @@ module AMQP
|
|
785
798
|
# @api public
|
786
799
|
def unsubscribe(opts = {}, &block)
|
787
800
|
@channel.once_open do
|
788
|
-
self.
|
801
|
+
self.once_name_is_available do
|
789
802
|
if @default_consumer
|
790
803
|
@default_consumer.cancel(opts.fetch(:nowait, true), &block); @default_consumer = nil
|
791
804
|
end
|
@@ -812,12 +825,14 @@ module AMQP
|
|
812
825
|
shim = Proc.new { |q, declare_ok| block.call(declare_ok.message_count, declare_ok.consumer_count) }
|
813
826
|
|
814
827
|
@channel.once_open do
|
815
|
-
|
816
|
-
|
817
|
-
|
828
|
+
self.once_name_is_available do
|
829
|
+
# we do not use self.declare here to avoid caching of @passive since that will cause unexpected side-effects during automatic
|
830
|
+
# recovery process. MK.
|
831
|
+
@connection.send_frame(AMQ::Protocol::Queue::Declare.encode(@channel.id, @name, true, @opts[:durable], @opts[:exclusive], @opts[:auto_delete], false, @opts[:arguments]))
|
818
832
|
|
819
|
-
|
820
|
-
|
833
|
+
self.append_callback(:declare, &shim)
|
834
|
+
@channel.queues_awaiting_declare_ok.push(self)
|
835
|
+
end
|
821
836
|
end
|
822
837
|
|
823
838
|
self
|
@@ -883,6 +898,16 @@ module AMQP
|
|
883
898
|
{ :queue => name, :nowait => (block.nil? && !name.empty?) }.merge(opts)
|
884
899
|
end
|
885
900
|
|
901
|
+
def once_name_is_available(&block)
|
902
|
+
if server_named?
|
903
|
+
self.once_declared do
|
904
|
+
block.call
|
905
|
+
end
|
906
|
+
else
|
907
|
+
block.call
|
908
|
+
end
|
909
|
+
end
|
910
|
+
|
886
911
|
private
|
887
912
|
|
888
913
|
# Default direct exchange that we use to publish messages directly to this queue.
|
data/lib/amqp/session.rb
CHANGED
@@ -110,7 +110,7 @@ module AMQP
|
|
110
110
|
|
111
111
|
|
112
112
|
# Properly close connection with AMQ broker, as described in
|
113
|
-
# section 2.2.4 of the {http://
|
113
|
+
# section 2.2.4 of the {http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Specification.pdf AMQP 0.9.1 specification}.
|
114
114
|
#
|
115
115
|
# @api plugin
|
116
116
|
# @see #close_connection
|
@@ -129,19 +129,19 @@ module AMQP
|
|
129
129
|
# Server properties (product information, platform, et cetera)
|
130
130
|
#
|
131
131
|
# @return [Hash]
|
132
|
-
# @see http://
|
132
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Reference.pdf AMQP 0.9.1 protocol documentation (Section 1.4.2.1.3)
|
133
133
|
attr_reader :server_properties
|
134
134
|
|
135
135
|
# Server capabilities (usually used to detect AMQP 0.9.1 extensions like basic.nack, publisher
|
136
136
|
# confirms and so on)
|
137
137
|
#
|
138
138
|
# @return [Hash]
|
139
|
-
# @see http://
|
139
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Reference.pdf AMQP 0.9.1 protocol documentation (Section 1.4.2.1.3)
|
140
140
|
attr_reader :server_capabilities
|
141
141
|
|
142
142
|
# Locales server supports
|
143
143
|
#
|
144
|
-
# @see http://
|
144
|
+
# @see http://files.travis-ci.org/docs/amqp/0.9.1/AMQP091Reference.pdf AMQP 0.9.1 protocol documentation (Section 1.4.2.1.3)
|
145
145
|
attr_reader :server_locales
|
146
146
|
|
147
147
|
# @return [AMQP::Broker] Broker this connection is established with
|
@@ -186,7 +186,7 @@ module AMQP
|
|
186
186
|
super(&block)
|
187
187
|
end
|
188
188
|
|
189
|
-
# Defines a callback that will be run when
|
189
|
+
# Defines a callback that will be run when TCP connection to AMQP broker is lost (interrupted).
|
190
190
|
# You can define only one callback.
|
191
191
|
#
|
192
192
|
# @api public
|
data/lib/amqp/version.rb
CHANGED
@@ -24,9 +24,7 @@ describe AMQP::Queue, "#pop" do
|
|
24
24
|
@exchange = @channel.fanout("amqpgem.integration.basic.get.queue", :auto_delete => true)
|
25
25
|
@queue = @channel.queue(@queue_name, :auto_delete => true)
|
26
26
|
|
27
|
-
@queue.bind(@exchange)
|
28
|
-
puts "Bound #{@exchange.name} => #{@queue.name}"
|
29
|
-
end
|
27
|
+
@queue.bind(@exchange)
|
30
28
|
|
31
29
|
@dispatched_data = "fetch me synchronously"
|
32
30
|
end
|
@@ -61,36 +59,93 @@ describe AMQP::Queue, "#pop" do
|
|
61
59
|
|
62
60
|
context "when THERE ARE messages in the queue" do
|
63
61
|
it "yields message payload to the callback" do
|
64
|
-
|
65
|
-
expected_number_of_messages = 300
|
66
|
-
|
67
|
-
expected_number_of_messages.times do |i|
|
68
|
-
@exchange.publish(@dispatched_data + "_#{i}", :key => @queue_name)
|
69
|
-
end
|
62
|
+
@channel.default_exchange.publish(@dispatched_data, :routing_key => @queue.name)
|
70
63
|
|
71
|
-
@queue.
|
72
|
-
|
73
|
-
@queue.pop do |headers, payload|
|
74
|
-
payload.should_not be_nil
|
75
|
-
number_of_received_messages += 1
|
76
|
-
headers.message_count.should == (expected_number_of_messages - number_of_received_messages)
|
77
|
-
|
78
|
-
if RUBY_VERSION =~ /^1.9/
|
79
|
-
payload.force_encoding("UTF-8").should =~ /#{@dispatched_data}/
|
80
|
-
else
|
81
|
-
payload.should =~ /#{@dispatched_data}/
|
82
|
-
end
|
83
|
-
end # pop
|
84
|
-
end # do
|
64
|
+
@queue.pop do |headers, payload|
|
65
|
+
payload.should == @dispatched_data
|
85
66
|
end
|
86
67
|
|
87
|
-
delayed(
|
68
|
+
delayed(0.5) {
|
88
69
|
# Queue.Get doesn't qualify for subscription, hence, manual deletion is required
|
89
70
|
@queue.delete
|
90
71
|
}
|
91
|
-
done(
|
92
|
-
number_of_received_messages.should == expected_number_of_messages
|
93
|
-
}
|
72
|
+
done(0.8)
|
94
73
|
end # it
|
95
74
|
end # context
|
75
|
+
|
76
|
+
|
77
|
+
context "with manual acknowledgements" do
|
78
|
+
default_timeout 4
|
79
|
+
|
80
|
+
let(:queue_name) { "amqpgem.integration.basic.get.acks.manual#{rand}" }
|
81
|
+
|
82
|
+
it "does not remove messages from the queue unless ack-ed" do
|
83
|
+
ch1 = AMQP::Channel.new
|
84
|
+
ch2 = AMQP::Channel.new
|
85
|
+
|
86
|
+
ch1.on_error do |ch, close_ok|
|
87
|
+
puts "Channel error: #{close_ok.reply_code} #{close_ok.reply_text}"
|
88
|
+
end
|
89
|
+
|
90
|
+
q = ch1.queue(queue_name, :exclusive => true)
|
91
|
+
x = ch1.default_exchange
|
92
|
+
|
93
|
+
q.purge
|
94
|
+
delayed(0.2) { x.publish(@dispatched_data, :routing_key => q.name) }
|
95
|
+
|
96
|
+
delayed(0.5) {
|
97
|
+
q.pop(:ack => true) do |meta, payload|
|
98
|
+
# never ack
|
99
|
+
end
|
100
|
+
|
101
|
+
ch1.close
|
102
|
+
|
103
|
+
EventMachine.add_timer(0.7) {
|
104
|
+
ch2.queue(queue_name, :exclusive => true).status do |number_of_messages, number_of_consumers|
|
105
|
+
number_of_messages.should == 1
|
106
|
+
done
|
107
|
+
end
|
108
|
+
}
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
context "with automatic acknowledgements" do
|
116
|
+
default_timeout 4
|
117
|
+
|
118
|
+
let(:queue_name) { "amqpgem.integration.basic.get.acks.automatic#{rand}" }
|
119
|
+
|
120
|
+
it "does remove messages from the queue after delivery" do
|
121
|
+
ch1 = AMQP::Channel.new
|
122
|
+
ch2 = AMQP::Channel.new
|
123
|
+
|
124
|
+
ch1.on_error do |ch, close_ok|
|
125
|
+
puts "Channel error: #{close_ok.reply_code} #{close_ok.reply_text}"
|
126
|
+
end
|
127
|
+
|
128
|
+
q = ch1.queue(queue_name, :exclusive => true)
|
129
|
+
x = ch1.default_exchange
|
130
|
+
|
131
|
+
q.purge
|
132
|
+
x.publish(@dispatched_data, :routing_key => q.name)
|
133
|
+
|
134
|
+
delayed(0.5) {
|
135
|
+
q.pop(:ack => false) do |meta, payload|
|
136
|
+
# never ack
|
137
|
+
end
|
138
|
+
|
139
|
+
ch1.close
|
140
|
+
|
141
|
+
EventMachine.add_timer(0.5) {
|
142
|
+
ch2.queue(queue_name, :exclusive => true).status do |number_of_messages, number_of_consumers|
|
143
|
+
number_of_messages.should == 0
|
144
|
+
done
|
145
|
+
end
|
146
|
+
}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
96
151
|
end # describe
|