amqp 0.8.0.rc6 → 0.8.0.rc7

Sign up to get free protection for your applications and to get access to all the features.
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
 
26
26
  # Dependencies
27
27
  s.add_dependency "eventmachine"
28
- s.add_dependency "amq-client", ">= 0.7.0.alpha18"
28
+ s.add_dependency "amq-client", ">= 0.7.0.alpha20"
29
29
 
30
30
  begin
31
31
  require "changelog"
@@ -51,7 +51,37 @@ TBD
51
51
 
52
52
  h3. Publisher confirms
53
53
 
54
- TBD
54
+ Because transactions carry certain (for some applications, significant) overhead, RabbitMQ introduced an extension to AMQP 0.9.1
55
+ called {http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/ publisher confirms} ({http://www.rabbitmq.com/extensions.html#confirms documentation}).
56
+
57
+ amqp gem implements support for this extension, but it is not loaded by default when you require "amqp". To load it, use
58
+
59
+ <pre>
60
+ <code>
61
+ require "amqp/extensions/rabbitmq"
62
+ </code>
63
+ </pre>
64
+
65
+ and then define a callback for publisher confirms using {AMQP::Channel#confirm}:
66
+
67
+ <pre>
68
+ <code>
69
+ # enable publisher acknowledgements for this channel
70
+ channel.confirm_select
71
+
72
+ # define a callback that will be executed when message is acknowledged
73
+ channel.on_ack do |basic_ack|
74
+ puts "Received an acknowledgement: delivery_tag = #{basic_ack.delivery_tag}, multiple = #{basic_ack.multiple}"
75
+ end
76
+
77
+ # define a callback that will be executed when message is rejected using basic.nack (a RabbitMQ-specific extension)
78
+ channel.on_nack do |basic_nack|
79
+ puts "Received a nack: delivery_tag = #{basic_nack.delivery_tag}, multiple = #{basic_nack.multiple}"
80
+ end
81
+ </code>
82
+ </pre>
83
+
84
+ Note that the same callback is used for all messages published via all exchanges on the given channel.
55
85
 
56
86
 
57
87
  h3. Clustering
@@ -344,6 +344,11 @@ end
344
344
  </code>
345
345
  </pre>
346
346
 
347
+ In books, articles and documentation about AMQP 0.9.1 you may come around discussions of _consumer tags_. Consumer tag in AMQP
348
+ parlance is an identifier for subscription: most often, it is used to unsubscribe from messages (more on that later in this chapter).
349
+ If you need to obtain consumer tag of a queue that is subscribed to receive messages, use {AMQP::Queue#consumer_tag}.
350
+
351
+
347
352
  h3. Exclusive consumers
348
353
 
349
354
  TBD
@@ -394,7 +399,42 @@ TBD
394
399
 
395
400
  h2. Unsubscribing from messages
396
401
 
397
- TBD
402
+ Sometimes it is necessary to unsubscribe from messages without deleting a queue. To do that, use {AMQP::Queue#unsubscribe} method:
403
+
404
+ <pre>
405
+ <code>
406
+ #!/usr/bin/env ruby
407
+ # encoding: utf-8
408
+
409
+ require "rubygems"
410
+ require "amqp"
411
+
412
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
413
+ AMQP::Channel.new do |channel, open_ok|
414
+ exchange = channel.fanout("amq.fanout")
415
+
416
+ channel.queue("", :auto_delete => true, :exclusive => true) do |queue, declare_ok|
417
+ queue.bind(exchange).subscribe do |headers, payload|
418
+ puts "Received a new message"
419
+ end
420
+
421
+ EventMachine.add_timer(0.3) do
422
+ queue.unsubscribe
423
+ puts "Unsubscribed. Shutting down..."
424
+
425
+ connection.close {
426
+ EM.stop { exit }
427
+ }
428
+ end # EventMachine.add_timer
429
+ end # channel.queue
430
+ end
431
+ end
432
+ </code>
433
+ </pre>
434
+
435
+ By default {AMQP::Queue#unsubscribe} uses :noack option to inform broker that there is no need to send a
436
+ confirmation. In other words, it does not expect you to pass in a callback, because consumer tag and registered
437
+ callbacks are cleared immediately.
398
438
 
399
439
 
400
440
  h2. Unbinding queues from exchanges
@@ -13,13 +13,13 @@ AMQP.start do |connection|
13
13
  AMQP::Channel.new(connection) do |channel|
14
14
  puts "Channel #{channel.id} is now open"
15
15
 
16
- channel.confirmations
16
+ channel.confirm_select
17
17
  channel.on_error do
18
18
  puts "Oops, there is a channel-levle exceptions!"
19
19
  end
20
20
 
21
21
 
22
- channel.confirm do |basic_ack|
22
+ channel.on_ack do |basic_ack|
23
23
  puts "Received basic_ack: multiple = #{basic_ack.multiple}, delivery_tag = #{basic_ack.delivery_tag}"
24
24
  end
25
25
 
@@ -50,4 +50,4 @@ AMQP.start do |connection|
50
50
  EM.add_timer(3, show_stopper)
51
51
  Signal.trap('INT', show_stopper)
52
52
  Signal.trap('TERM', show_stopper)
53
- end
53
+ end
@@ -4,8 +4,7 @@
4
4
  require "rubygems"
5
5
  require "amqp"
6
6
 
7
- #AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
8
- AMQP.start do |connection, open_ok|
7
+ AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
9
8
  AMQP::Channel.new do |channel, open_ok|
10
9
  exchange = channel.fanout("amq.fanout")
11
10
 
@@ -15,14 +14,12 @@ AMQP.start do |connection, open_ok|
15
14
  end
16
15
 
17
16
  EventMachine.add_timer(0.3) do
18
- puts "Timer tick"
19
- queue.unsubscribe do |_|
20
- puts "Unsubscribed. Shutting down..."
17
+ queue.unsubscribe
18
+ puts "Unsubscribed. Shutting down..."
21
19
 
22
- connection.close {
23
- EM.stop { exit }
24
- }
25
- end
20
+ connection.close {
21
+ EM.stop { exit }
22
+ }
26
23
  end # EventMachine.add_timer
27
24
  end # channel.queue
28
25
  end
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require "bundler"
5
+ Bundler.setup
6
+
7
+ $:.unshift(File.expand_path("../../../lib", __FILE__))
8
+
9
+ require 'amqp'
10
+
11
+ if RUBY_VERSION == "1.8.7"
12
+ class Array
13
+ alias sample choice
14
+ end
15
+ end
16
+
17
+ puts "=> Publishing and immediately stopping the event loop in the callback"
18
+ puts
19
+
20
+ # WARNING: this example is born out of http://bit.ly/j6v1Uz (#67) and
21
+ # by no means a demonstration of how you should go about publishing one-off messages.
22
+ # If durability is a concern, please read our "Durability and message persistence" guide at
23
+ # http://bit.ly/lQP1Al
24
+
25
+ EventMachine.run do
26
+ client = AMQP.connect(:host => '127.0.0.1')
27
+ channel = AMQP::Channel.new(client)
28
+ channel.on_error { puts 'channel error'; EM.stop }
29
+
30
+ queue = channel.queue("some_topic", :auto_delete => true)
31
+ exchange = channel.topic("foo", :durable => true, :auto_delete => true)
32
+
33
+ exchange.publish( 'hello world', :routing_key => "some_topic", :persistent => true, :nowait => false ) do
34
+ puts 'enqueued message for publishing on next event loop tick'
35
+ EventMachine.stop
36
+ end
37
+ end
@@ -364,6 +364,8 @@ module AMQP
364
364
  # and distributed to any active consumers. Routing logic is determined by exchange type and
365
365
  # configuration as well as message attributes (like :routing_key).
366
366
  #
367
+ #
368
+ #
367
369
  # h2. Data serialization
368
370
  #
369
371
  # Note that this method calls #to_s on payload argument value. You are encouraged to take care of
@@ -375,7 +377,30 @@ module AMQP
375
377
  #
376
378
  # h2. Event loop blocking
377
379
  #
378
- # To minimize blocking of EventMachine event loop, this method performs network I/O on the next event loop tick.
380
+ # To minimize blocking of EventMachine event loop, this method performs network I/O on the next event loop tick. This means
381
+ # that shutting down the event loop immediately after {Exchange#publish} returns will result in message never being sent.
382
+ # If you need to send a one-off message and then stop the event loop, pass a block to {Exchange#publish} that will be executed
383
+ # after message is pushed down the network stack, and use {AMQP::Session#disconnect} to properly tear down AMQP connection
384
+ # (see example under Examples section below).
385
+ #
386
+ # @example Publishing a one-off message and properly closing AMQP connection then stopping the event loop:
387
+ # exchange.publish(data) do
388
+ # connection.disconnect { EventMachine.stop }
389
+ # end
390
+ #
391
+ #
392
+ # h2. Publishing and persistence
393
+ #
394
+ # In cases when you application cannot afford to lose a message, AMQP 0.9.1 has several features to offer:
395
+ #
396
+ # * Persistent messages
397
+ # * Messages acknowledgements
398
+ # * Transactions
399
+ # * (a RabbitMQ-specific extension) Publisher confirms
400
+ #
401
+ # This is a broad topic and we dedicate a separate guide, {file:docs/Durability.textile Durability and message persistence}, to it.
402
+ #
403
+ #
379
404
  #
380
405
  # @param [#to_s] payload Message payload (content). Note that this method calls #to_s on payload argument value.
381
406
  # You are encouraged to take care of data serialization before publishing (using JSON, Thrift,
@@ -425,7 +450,11 @@ module AMQP
425
450
  opts = @default_publish_options.merge(options)
426
451
 
427
452
  @channel.once_open do
428
- super(payload.to_s, opts[:key] || opts[:routing_key] || @default_routing_key, @default_headers.merge(options), opts[:mandatory], opts[:immediate], &block)
453
+ super(payload.to_s, opts[:key] || opts[:routing_key] || @default_routing_key, @default_headers.merge(options), opts[:mandatory], opts[:immediate])
454
+
455
+ # don't pass block to AMQ::Client::Exchange#publish because it will be executed
456
+ # immediately and we want to do it later. See ruby-amqp/amqp/#67 MK.
457
+ block.call if block
429
458
  end
430
459
  end
431
460
 
@@ -573,7 +573,7 @@ module AMQP
573
573
  # The method accepts a block which will be executed when the
574
574
  # unsubscription request is acknowledged as complete by the server.
575
575
  #
576
- # @option opts [Boolean] :nowait (false) If set, the server will not respond to the method. The client should
576
+ # @option opts [Boolean] :nowait (true) If set, the server will not respond to the method. The client should
577
577
  # not wait for a reply method. If the server could not complete the
578
578
  # method it will raise a channel or connection exception.
579
579
  #
@@ -6,5 +6,5 @@ module AMQP
6
6
  #
7
7
  # @see AMQ::Protocol::VERSION
8
8
  # @return [String] AMQP gem version
9
- VERSION = '0.8.0.rc6'
9
+ VERSION = '0.8.0.rc7'
10
10
  end
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require "spec_helper"
3
3
 
4
- describe "Authentication attempt" do
4
+ describe "Immediate disconnection" do
5
5
 
6
6
  #
7
7
  # Environment
@@ -11,25 +11,14 @@ describe "Authentication attempt" do
11
11
  include EventedSpec::SpecHelper
12
12
 
13
13
 
14
- describe "with default connection parameters" do
14
+ after :all do
15
+ done
16
+ end
15
17
 
16
- #
17
- # Examples
18
- #
19
-
20
- # assuming there is an account guest with password of "guest" that has
21
- # access to / (default vhost)
22
- context "when guest/guest has access to /" do
23
- after :all do
24
- done
25
- end
26
-
27
- it "succeeds" do
28
- c = AMQP.connect
29
- c.disconnect
30
-
31
- done
32
- end # it
33
- end # context
34
- end # describe
18
+ it "succeeds" do
19
+ c = AMQP.connect
20
+ c.disconnect {
21
+ done
22
+ }
23
+ end # it
35
24
  end # describe "Authentication attempt"
metadata CHANGED
@@ -1,65 +1,49 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: amqp
3
- version: !ruby/object:Gem::Version
4
- hash: 977940491
5
- prerelease: true
6
- segments:
7
- - 0
8
- - 8
9
- - 0
10
- - rc6
11
- version: 0.8.0.rc6
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0.rc7
5
+ prerelease: 6
12
6
  platform: ruby
13
- authors:
7
+ authors:
14
8
  - Aman Gupta
15
9
  - Jakub Stastny aka botanicus
16
10
  - Michael S. Klishin
17
11
  autorequire:
18
12
  bindir: bin
19
13
  cert_chain:
20
- date: 2011-05-06 00:00:00 +04:00
14
+ date: 2011-05-06 00:00:00.000000000 +04:00
21
15
  default_executable:
22
- dependencies:
23
- - !ruby/object:Gem::Dependency
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
24
18
  name: eventmachine
25
- prerelease: false
26
- requirement: &id001 !ruby/object:Gem::Requirement
19
+ requirement: &2156551420 !ruby/object:Gem::Requirement
27
20
  none: false
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- hash: 3
32
- segments:
33
- - 0
34
- version: "0"
21
+ requirements:
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '0'
35
25
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: amq-client
39
26
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
27
+ version_requirements: *2156551420
28
+ - !ruby/object:Gem::Dependency
29
+ name: amq-client
30
+ requirement: &2156550900 !ruby/object:Gem::Requirement
41
31
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 1369027924
46
- segments:
47
- - 0
48
- - 7
49
- - 0
50
- - alpha18
51
- version: 0.7.0.alpha18
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 0.7.0.alpha20
52
36
  type: :runtime
53
- version_requirements: *id002
54
- description: Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries included
55
- email:
37
+ prerelease: false
38
+ version_requirements: *2156550900
39
+ description: Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries
40
+ included
41
+ email:
56
42
  - michael@novemberain.com
57
43
  - stastny@101ideas.cz
58
44
  executables: []
59
-
60
45
  extensions: []
61
-
62
- extra_rdoc_files:
46
+ extra_rdoc_files:
63
47
  - README.textile
64
48
  - docs/08Migration.textile
65
49
  - docs/Bindings.textile
@@ -75,7 +59,7 @@ extra_rdoc_files:
75
59
  - docs/RabbitMQVersions.textile
76
60
  - docs/Routing.textile
77
61
  - docs/VendorSpecificExtensions.textile
78
- files:
62
+ files:
79
63
  - .gitignore
80
64
  - .rspec
81
65
  - .travis.yml
@@ -144,6 +128,7 @@ files:
144
128
  - examples/legacy/primes-simple.rb
145
129
  - examples/legacy/primes.rb
146
130
  - examples/legacy/stocks.rb
131
+ - examples/publishing/publishing_and_immediately_stopping_event_loop.rb
147
132
  - examples/queues/automatic_binding_for_default_direct_exchange.rb
148
133
  - examples/queues/basic_get.rb
149
134
  - examples/queues/declare_a_queue_without_assignment.rb
@@ -219,38 +204,68 @@ files:
219
204
  has_rdoc: true
220
205
  homepage: http://github.com/ruby-amqp/amqp
221
206
  licenses: []
222
-
223
- post_install_message:
224
- rdoc_options:
207
+ post_install_message: ! "[\e[32mVersion 0.8.0\e[0m] [FEATURE] AMQP 0.9.1 support,
208
+ including tx.* operations class.\n[\e[32mVersion 0.8.0\e[0m] [API] Default authentication
209
+ handler now raises AMQP::PossibleAuthenticationFailureError\n[\e[32mVersion 0.8.0\e[0m]
210
+ [API] AMQP::Channel#initialize now takes 3rd (optional) options hash.\n[\e[32mVersion
211
+ 0.8.0\e[0m] [API] Broker connection class is now AMQP::Session.\n[\e[32mVersion
212
+ 0.8.0\e[0m] [API] AMQP::Error instance now may carry cause, an exception that caused
213
+ exception in question to be raised.\n[\e[32mVersion 0.8.0\e[0m] [API] When initial
214
+ TCP connection fails, default action is now to raise AMQP::TCPConnectionFailed.\n[\e[32mVersion
215
+ 0.8.0\e[0m] [API] AMQP::BasicClient#reconnect now takes 2nd optional argument, period
216
+ of waiting in seconds.\n[\e[32mVersion 0.8.0\e[0m] [FEATURE] Handlers for initial
217
+ connection failure, connection loss; channel-level exceptions handlers on Channel
218
+ instances.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Exchange#initialize now accepts
219
+ :arguments option that takes a hash.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Queue#initialize
220
+ now accepts :arguments option that takes a hash.\n[\e[32mVersion 0.8.0\e[0m] [API]
221
+ AMQP#Logger is deprecated. It will be removed before 1.0 release.\n[\e[32mVersion
222
+ 0.8.0\e[0m] [API] AMQP#fork is deprecated. It will be removed before 1.0 release.\n[\e[32mVersion
223
+ 0.8.0\e[0m] [API] AMQP::RPC is deprecated. It will be removed before 1.0 release.\n[\e[32mVersion
224
+ 0.8.0\e[0m] [FEATURE] Significant improvements to the documentation. From now on
225
+ lack of/poor documentation is considered a severe bug.\n[\e[32mVersion 0.8.0\e[0m]
226
+ [FEATURE] Support for RabbitMQ extensions to AMQP 0.9.1\n[\e[32mVersion 0.8.0\e[0m]
227
+ [API] AMQP::Exchange#publish now accepts (an optional) callback.\n[\e[32mVersion
228
+ 0.8.0\e[0m] [API] AMQP::Channel.new now accepts (an optional) callback.\n[\e[32mVersion
229
+ 0.8.0\e[0m] [API] AMQP::Header#ack now can acknowledge multiple deliveries\n[\e[32mVersion
230
+ 0.8.0\e[0m] [API] AMQP::Exchange#delete now takes (an optional) block that is called
231
+ when exchange.delete-ok response arrives.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Header
232
+ now implements #to_hash\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Queue#pop block
233
+ now can take 1, 2 or 3 arguments.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Queue#purge
234
+ \ now takes an optional block which is called when queue.purge-ok response arrives.\n[\e[32mVersion
235
+ 0.8.0\e[0m] [API] AMQP::Queue#delete now takes an optional block which is called
236
+ when queue.delete-ok response arrives.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Queue#delete
237
+ now accepts :nowait option.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Queue#unbind
238
+ now takes an optional block which is called when queue.unbind-ok response arrives.\n[\e[32mVersion
239
+ 0.8.0\e[0m] [API] AMQP::Queue#unbind now accepts :routing_key as alias to :key.
240
+ we believe it is a good idea to use AMQP terms.\n[\e[32mVersion 0.8.0\e[0m] [API]
241
+ AMQP::Channel#prefetch now takes (an optional) 2nd parameter that specifies that
242
+ QoS settings should be applied to underlying connection, as well as optional callback.\n[\e[32mVersion
243
+ 0.8.0\e[0m] [API] AMQP::Channel#recover now takes (an optional) callback that is
244
+ called when basic.recover-ok is received.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Frame
245
+ is gone.\n[\e[32mVersion 0.8.0\e[0m] [API] AMQP::Buffer is gone. Serialization &
246
+ framing are now handled primarily by amq-protocol.\n[\e[32mVersion 0.8.0\e[0m] [API]
247
+ AMQP::Queue#publish is deprecated.\n[\e[32mVersion 0.8.0\e[0m] [API] Name argument
248
+ for AMQP::Queue.new and Channel#queue is optional.\n"
249
+ rdoc_options:
225
250
  - --include=examples --main README.textile
226
- require_paths:
251
+ require_paths:
227
252
  - lib
228
- required_ruby_version: !ruby/object:Gem::Requirement
253
+ required_ruby_version: !ruby/object:Gem::Requirement
229
254
  none: false
230
- requirements:
231
- - - ">="
232
- - !ruby/object:Gem::Version
233
- hash: 3
234
- segments:
235
- - 0
236
- version: "0"
237
- required_rubygems_version: !ruby/object:Gem::Requirement
255
+ requirements:
256
+ - - ! '>='
257
+ - !ruby/object:Gem::Version
258
+ version: '0'
259
+ required_rubygems_version: !ruby/object:Gem::Requirement
238
260
  none: false
239
- requirements:
240
- - - ">"
241
- - !ruby/object:Gem::Version
242
- hash: 25
243
- segments:
244
- - 1
245
- - 3
246
- - 1
261
+ requirements:
262
+ - - ! '>'
263
+ - !ruby/object:Gem::Version
247
264
  version: 1.3.1
248
265
  requirements: []
249
-
250
266
  rubyforge_project: amqp
251
- rubygems_version: 1.3.7
267
+ rubygems_version: 1.6.2
252
268
  signing_key:
253
269
  specification_version: 3
254
270
  summary: AMQP client implementation in Ruby/EventMachine.
255
271
  test_files: []
256
-