amqp 1.0.0.pre2 → 1.0.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.
- 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
|