amqp 0.8.0.rc2 → 0.8.0.rc3
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 +2 -3
- data/.travis.yml +5 -2
- data/.yardopts +2 -0
- data/CHANGELOG +17 -20
- data/Gemfile +7 -5
- data/README.textile +67 -29
- data/Rakefile +6 -0
- data/amqp.gemspec +5 -5
- data/docs/08Migration.textile +27 -0
- data/docs/Bindings.textile +27 -0
- data/docs/ConnectingToTheBroker.textile +277 -0
- data/docs/DocumentationGuidesIndex.textile +25 -0
- data/docs/Durability.textile +27 -0
- data/docs/ErrorHandling.textile +84 -0
- data/docs/Exchanges.textile +27 -0
- data/docs/GettingStarted.textile +585 -0
- data/docs/Queues.textile +27 -0
- data/docs/RabbitMQVersions.textile +12 -2
- data/docs/Routing.textile +27 -0
- data/docs/TLS.textile +27 -0
- data/docs/VendorSpecificExtensions.textile +11 -1
- data/examples/{various → channels}/open_channel_without_assignment.rb +0 -4
- data/examples/channels/prefetch_as_constructor_argument.rb +31 -0
- data/examples/channels/qos_aka_prefetch.rb +34 -0
- data/examples/channels/qos_aka_prefetch_without_callback.rb +32 -0
- data/examples/error_handling/channel_level_exception.rb +47 -0
- data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +54 -0
- data/examples/error_handling/connection_loss_handler.rb +39 -0
- data/examples/error_handling/global_channel_level_exception_handler.rb +65 -0
- data/examples/error_handling/handling_authentication_failure_with_a_callback.rb +33 -0
- data/examples/error_handling/tcp_connection_failure_handling_with_a_rescue_block.rb +30 -0
- data/examples/error_handling/tcp_connection_failure_with_a_callback.rb +28 -0
- data/examples/{various → exchanges}/declare_an_exchange_without_assignment.rb +0 -4
- data/examples/guides/getting_started/01_hello_world.rb +24 -0
- data/examples/guides/getting_started/02_hello_world_dslified.rb +23 -0
- data/examples/guides/getting_started/03_babblr.rb +33 -0
- data/examples/guides/getting_started/04_weathr.rb +56 -0
- data/examples/hello_world.rb +12 -13
- data/examples/hello_world_with_eventmachine_in_a_separate_thread.rb +37 -0
- data/examples/{various → legacy}/ack.rb +0 -0
- data/examples/{various → legacy}/callbacks.rb +0 -0
- data/examples/{various → legacy}/clock.rb +0 -0
- data/examples/{various → legacy}/hashtable.rb +0 -0
- data/examples/{various → legacy}/logger.rb +0 -0
- data/examples/{various → legacy}/multiclock.rb +0 -0
- data/examples/{various → legacy}/pingpong.rb +0 -2
- data/examples/{various → legacy}/primes-simple.rb +0 -0
- data/examples/{various → legacy}/primes.rb +0 -2
- data/examples/{various → legacy}/stocks.rb +0 -0
- data/examples/{various → queues}/automatic_binding_for_default_direct_exchange.rb +4 -0
- data/examples/{various → queues}/basic_get.rb +0 -2
- data/examples/{various → queues}/declare_a_queue_without_assignment.rb +0 -4
- data/examples/queues/declare_and_bind_a_server_named_queue.rb +43 -0
- data/examples/{various → queues}/queue_status.rb +3 -8
- data/examples/{various → routing}/pubsub.rb +0 -0
- data/examples/{various → routing}/weather_updates.rb +1 -1
- data/lib/amqp/channel.rb +231 -52
- data/lib/amqp/client.rb +6 -3
- data/lib/amqp/connection.rb +9 -10
- data/lib/amqp/deprecated/fork.rb +3 -3
- data/lib/amqp/deprecated/logger.rb +1 -0
- data/lib/amqp/deprecated/mq.rb +23 -1
- data/lib/amqp/deprecated/rpc.rb +1 -0
- data/lib/amqp/exceptions.rb +45 -3
- data/lib/amqp/exchange.rb +29 -35
- data/lib/amqp/ext/em.rb +0 -7
- data/lib/amqp/ext/emfork.rb +3 -2
- data/lib/amqp/header.rb +4 -0
- data/lib/amqp/queue.rb +96 -33
- data/lib/amqp/session.rb +140 -0
- data/lib/amqp/version.rb +6 -1
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +7 -7
- data/spec/integration/channel_level_exception_with_multiple_channels_spec.rb +69 -0
- data/spec/integration/declare_and_immediately_bind_a_server_named_queue_spec.rb +42 -0
- data/spec/integration/queue_declaration_spec.rb +8 -24
- data/spec/integration/queue_redeclaration_with_incompatible_attributes_spec.rb +43 -0
- data/spec/unit/amqp/connection_spec.rb +1 -1
- metadata +200 -182
- data/lib/amqp/basic_client.rb +0 -27
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/CHANGELOG
CHANGED
|
@@ -1,35 +1,32 @@
|
|
|
1
1
|
= Version 0.8.0
|
|
2
2
|
|
|
3
|
-
* [
|
|
4
|
-
|
|
5
|
-
* [API]
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
* [FEATURE] AMQP 0.9.1 support, including tx.* operations class.
|
|
4
|
+
* [API] AMQP::Channel#initialize now takes 3rd (optional) options hash.
|
|
5
|
+
* [API] Broker connection class is now AMQP::Session.
|
|
6
|
+
* [API] AMQP::Error instance now may carry cause, an exception that caused exception in question to be raised.
|
|
7
|
+
* [API] When initial TCP connection fails, default action is now to raise AMQP::TCPConnectionFailed.
|
|
8
|
+
* [API] AMQP::BasicClient#reconnect now takes 2nd optional argument, period of waiting in seconds.
|
|
9
|
+
* [FEATURE] Handlers for initial connection failre, connection loss; channel-level exceptions handlers on Channel instances.
|
|
10
|
+
* [API] AMQP::Exchange#initialize now accepts :arguments option that takes a hash.
|
|
11
|
+
* [API] AMQP::Queue#initialize now accepts :arguments option that takes a hash.
|
|
8
12
|
* [API] AMQP#Logger is deprecated. It will be removed before 1.0 release.
|
|
9
13
|
* [API] AMQP#fork is deprecated. It will be removed before 1.0 release.
|
|
10
14
|
* [API] AMQP::RPC is deprecated. It will be removed before 1.0 release.
|
|
11
|
-
* [FEATURE] Significant improvements to the documentation
|
|
15
|
+
* [FEATURE] Significant improvements to the documentation. From now on lack of/poor documentation is considered a severe bug.
|
|
12
16
|
* [FEATURE] Support for RabbitMQ extensions to AMQP 0.9.1
|
|
13
|
-
* [API] AMQP::Exchange#publish now accepts (an optional)
|
|
14
|
-
|
|
15
|
-
* [API] AMQP::Channel.new now accepts (an optional) block and yields newly opened channel to it as soon as
|
|
16
|
-
channel.open-ok arrives from the broker.
|
|
17
|
+
* [API] AMQP::Exchange#publish now accepts (an optional) callback.
|
|
18
|
+
* [API] AMQP::Channel.new now accepts (an optional) callback.
|
|
17
19
|
* [API] AMQP::Header#ack now can acknowledge multiple deliveries
|
|
18
20
|
* [API] AMQP::Exchange#delete now takes (an optional) block that is called when exchange.delete-ok response arrives.
|
|
19
21
|
* [API] AMQP::Header now implements #to_hash
|
|
20
22
|
* [API] AMQP::Queue#pop block now can take 1, 2 or 3 arguments.
|
|
21
|
-
1 argument means handler is only interested in content payload
|
|
22
|
-
2 arguments mean handler is interested in headers and the content
|
|
23
|
-
3 arguments mean handler is interested in headers, content and AMQP method instance
|
|
24
23
|
* [API] AMQP::Queue#purge now takes an optional block which is called when queue.purge-ok response arrives.
|
|
25
24
|
* [API] AMQP::Queue#delete now takes an optional block which is called when queue.delete-ok response arrives.
|
|
26
25
|
* [API] AMQP::Queue#delete now accepts :nowait option.
|
|
27
26
|
* [API] AMQP::Queue#unbind now takes an optional block which is called when queue.unbind-ok response arrives.
|
|
28
27
|
* [API] AMQP::Queue#unbind now accepts :routing_key as alias to :key. we believe it is a good idea to use AMQP terms.
|
|
29
|
-
* [API] AMQP::Channel#prefetch now takes (an optional) 2nd parameter that specifies
|
|
30
|
-
|
|
31
|
-
* [API] AMQP::Channel#recover now takes (an optional) callback that is called when
|
|
32
|
-
basic.recover-ok is received.
|
|
28
|
+
* [API] AMQP::Channel#prefetch now takes (an optional) 2nd parameter that specifies that QoS settings should be applied to underlying connection, as well as optional callback.
|
|
29
|
+
* [API] AMQP::Channel#recover now takes (an optional) callback that is called when basic.recover-ok is received.
|
|
33
30
|
* [API] AMQP::Frame is gone.
|
|
34
31
|
* [API] AMQP::Buffer is gone. Serialization & framing are now handled primarily by amq-protocol.
|
|
35
32
|
* [FEATURE] AMQP gem is now AMQP 0.9.1 compatible: it runs atop of amq-client gem
|
|
@@ -40,11 +37,11 @@
|
|
|
40
37
|
|
|
41
38
|
* [BUG] AMQP gem no longer conflicts with Builder 2.1.2 on Ruby 1.9.
|
|
42
39
|
All Ruby on Rails 3 users who run Ruby 1.9 are highly recommended
|
|
43
|
-
|
|
40
|
+
to upgrade!
|
|
44
41
|
* [API] AMQP::Exchange.default no longer caches exchange object between calls
|
|
45
42
|
because it may lead to very obscure issues when channel that exchange was
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
using is closed (due to connection loss, as part of test suite teardown
|
|
44
|
+
or in any other way).
|
|
48
45
|
|
|
49
46
|
* [API] AMQP::Exchange.default now accepts channel as a parameter.
|
|
50
47
|
* [API] AMQP::Exchange#channel
|
data/Gemfile
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
-
source
|
|
3
|
+
source :rubygems
|
|
4
4
|
|
|
5
5
|
# Use local clones if possible.
|
|
6
|
+
# If you want to use your local copy, just symlink it to vendor.
|
|
6
7
|
def custom_gem(name, options = Hash.new)
|
|
7
|
-
local_path = File.expand_path("
|
|
8
|
-
if
|
|
8
|
+
local_path = File.expand_path("../vendor/#{name}", __FILE__)
|
|
9
|
+
if File.exist?(local_path)
|
|
9
10
|
gem name, options.merge(:path => local_path).delete_if { |key, _| [:git, :branch].include?(key) }
|
|
10
11
|
else
|
|
11
12
|
gem name, options
|
|
12
13
|
end
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
custom_gem "eventmachine"
|
|
16
17
|
gem "json", :platform => :ruby_18
|
|
17
18
|
custom_gem "amq-client", :git => "git://github.com/ruby-amqp/amq-client.git", :branch => "master"
|
|
18
19
|
custom_gem "amq-protocol", :git => "git://github.com/ruby-amqp/amq-protocol.git", :branch => "master"
|
|
@@ -27,6 +28,7 @@ group(:development) do
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
group(:test) do
|
|
30
|
-
gem "rspec", ">=2.
|
|
31
|
+
gem "rspec", ">=2.5.0"
|
|
32
|
+
gem "rake"
|
|
31
33
|
custom_gem "evented-spec", :git => "git://github.com/ruby-amqp/evented-spec.git", :branch => "master"
|
|
32
34
|
end
|
data/README.textile
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
h1. About amqp gem "!http://travis-ci.org/ruby-amqp/amqp.png!":http://travis-ci.org/ruby-amqp/amqp
|
|
2
2
|
|
|
3
|
-
amqp gem is a widely used, feature-rich asynchronous
|
|
3
|
+
amqp gem is a widely used, feature-rich, well-maintained asynchronous AMQP 0.9.1 client with batteries included.
|
|
4
4
|
This library works with Ruby 1.8.7, Ruby 1.9.2, JRuby, REE and Rubinius, and is
|
|
5
5
|
licensed under the "Ruby License":http://www.ruby-lang.org/en/LICENSE.txt.
|
|
6
6
|
Versions 0.8.0 and later of amqp gem implement "AMQP 0.9.1":http://bit.ly/hw2ELX.
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
h2. I know what AMQP is, how do I get started?
|
|
10
|
+
|
|
11
|
+
See "Getting started with amqp gem" and "Documentation: tutorials, guides & API reference" sections below.
|
|
12
|
+
|
|
13
|
+
|
|
9
14
|
h2. What is AMQP?
|
|
10
15
|
|
|
11
16
|
AMQP is an "open standard for messaging middleware":http://www.amqp.org/confluence/display/AMQP/About+AMQP that
|
|
@@ -32,7 +37,7 @@ Specific examples:
|
|
|
32
37
|
there are some new results.
|
|
33
38
|
|
|
34
39
|
* Content aggregators may update full-text search and geospatial search indexes
|
|
35
|
-
|
|
40
|
+
by delegating actual indexing work to other applications over AMQP.
|
|
36
41
|
|
|
37
42
|
* Companies may provide "Firehose-like" push APIs to their customers, partners
|
|
38
43
|
or just general public.
|
|
@@ -42,11 +47,11 @@ Specific examples:
|
|
|
42
47
|
|
|
43
48
|
* An application that watches updates from a real-time stream (be it markets data
|
|
44
49
|
or Twitter stream) can propagate updates to interested parties, including
|
|
45
|
-
|
|
50
|
+
Web applications that display that information in the real time.
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
|
|
49
|
-
h2. Getting started with amqp gem
|
|
54
|
+
h2(Getting_started_with_amqp_gem). Getting started with amqp gem
|
|
50
55
|
|
|
51
56
|
h3. Install RabbitMQ
|
|
52
57
|
|
|
@@ -62,37 +67,77 @@ h3. Install the gem
|
|
|
62
67
|
|
|
63
68
|
h3. "Hello, World" example
|
|
64
69
|
|
|
65
|
-
<pre>
|
|
70
|
+
<pre><code>
|
|
66
71
|
#!/usr/bin/env ruby
|
|
67
72
|
# encoding: utf-8
|
|
68
73
|
|
|
69
74
|
require "rubygems"
|
|
75
|
+
# or
|
|
76
|
+
#
|
|
77
|
+
# require "bundler"
|
|
78
|
+
# Bundler.setup
|
|
79
|
+
#
|
|
80
|
+
# if you use Bundler
|
|
81
|
+
|
|
70
82
|
require 'amqp'
|
|
71
83
|
|
|
72
84
|
EventMachine.run do
|
|
73
|
-
AMQP.connect(:host => '
|
|
74
|
-
|
|
85
|
+
connection = AMQP.connect(:host => '127.0.0.1')
|
|
86
|
+
puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
channel = AMQP::Channel.new(connection)
|
|
89
|
+
queue = channel.queue("amqpgem.examples.hello_world", :auto_delete => true)
|
|
90
|
+
exchange = channel.direct("")
|
|
79
91
|
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
queue.subscribe do |payload|
|
|
93
|
+
puts "Received a message: #{payload}. Disconnecting..."
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
connection.close {
|
|
96
|
+
EM.stop { exit }
|
|
97
|
+
}
|
|
98
|
+
end
|
|
87
99
|
|
|
88
|
-
|
|
89
|
-
end
|
|
100
|
+
exchange.publish "Hello, world!", :routing_key => queue.name
|
|
90
101
|
end
|
|
91
|
-
</pre>
|
|
102
|
+
</code></pre>
|
|
92
103
|
|
|
93
104
|
(see "as a Gist":https://gist.github.com/910211)
|
|
94
105
|
|
|
95
106
|
|
|
107
|
+
|
|
108
|
+
h2(#Documentation_tutorials_guides_API_reference). Documentation: tutorials, guides & API reference
|
|
109
|
+
|
|
110
|
+
We believe that in order to be the best Ruby AMQP client out there, we need to care about documentation as much as
|
|
111
|
+
code readability, API beauty and autotomated testing across 5 Ruby implementations on 3 operating systems.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
h3. Tutorials
|
|
115
|
+
|
|
116
|
+
We have written and maintain "Getting started guide":http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/GettingStarted.textile that is written in form of a tutorial.
|
|
117
|
+
Check it out! If something isn't clear, every guide explains how to contact documentation authors.
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
h3. Examples
|
|
121
|
+
|
|
122
|
+
You can find many examples (both real-world cases and simple demonstrations)
|
|
123
|
+
under "examples directory":https://github.com/ruby-amqp/amqp/tree/master/examples in the repository.
|
|
124
|
+
Note that those examples are written against version 0.8.0.rc1 and later. 0.6.x and 0.7.x
|
|
125
|
+
may not support certain AMQP protocol or "DSL syntax" features.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
h3. Guides
|
|
129
|
+
|
|
130
|
+
"Documentation guides":http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/DocumentationGuidesIndex.textile describe
|
|
131
|
+
the library itself as well as AMQP usage scenarios, routing, error handing & recovery, broker-specific extensions, TLS support and so on.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
h3. API reference
|
|
135
|
+
|
|
136
|
+
"Reference documentation":http://rdoc.info/github/ruby-amqp/amqp/master/frames is up on rdoc.info and is updated daily.
|
|
137
|
+
|
|
138
|
+
*If you don't find your answer in documentation, we consider it a high severity bug* that you should "file to us":http://github.com/ruby-amqp/amqp/issues.
|
|
139
|
+
|
|
140
|
+
|
|
96
141
|
h2. How to use AMQP gem with Ruby on Rails, Merb, Sinatra and other web frameworks
|
|
97
142
|
|
|
98
143
|
To use AMQP gem from web applications, you would need to have EventMachine reactor running.
|
|
@@ -141,13 +186,6 @@ gem "amqp", :git => "git://github.com/ruby-amqp/amqp.git", :branch => "master"
|
|
|
141
186
|
|
|
142
187
|
|
|
143
188
|
|
|
144
|
-
h2. Examples
|
|
145
|
-
|
|
146
|
-
You can find many examples (both real-world cases and simple demonstrations)
|
|
147
|
-
under "examples directory":https://github.com/ruby-amqp/amqp/tree/master/examples in the repository.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
189
|
h2. How does amqp gem relate to amq-client gem, amq-protocol and libraries like bunny?
|
|
152
190
|
|
|
153
191
|
See "this page about AMQP gems family":https://github.com/ruby-amqp/amq-client/blob/master/README.textile
|
|
@@ -209,7 +247,7 @@ use version 0.7.
|
|
|
209
247
|
|
|
210
248
|
h2. Links
|
|
211
249
|
|
|
212
|
-
* "API
|
|
250
|
+
* "API reference":http://rdoc.info/github/ruby-amqp/amqp/master/frames
|
|
213
251
|
* "Examples":https://github.com/ruby-amqp/amq-protocol/tree/master/examples/
|
|
214
|
-
* "Issue tracker":http://github.com/ruby-amqp/
|
|
215
|
-
* "Continous integration server":http://travis-ci.org/#!/ruby-amqp/amqp
|
|
252
|
+
* "Issue tracker":http://github.com/ruby-amqp/amqp/issues
|
|
253
|
+
* "Continous integration server":http://travis-ci.org/#!/ruby-amqp/amqp
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
require 'fileutils'
|
|
1
2
|
require 'rspec/core/rake_task'
|
|
2
3
|
|
|
3
4
|
desc "Run spec suite (uses Rspec2)"
|
|
4
5
|
RSpec::Core::RakeTask.new(:spec) { |t|}
|
|
5
6
|
|
|
7
|
+
namespace :spec do
|
|
8
|
+
desc "Clean up rbx compiled files and run spec suite"
|
|
9
|
+
RSpec::Core::RakeTask.new(:ci) { |t| Dir.glob("**/*.rbc").each {|f| FileUtils.rm_f(f) } }
|
|
10
|
+
end
|
|
11
|
+
|
|
6
12
|
desc "Run specs with RCov"
|
|
7
13
|
RSpec::Core::RakeTask.new(:rcov) do |t|
|
|
8
14
|
t.rcov = true
|
data/amqp.gemspec
CHANGED
|
@@ -10,22 +10,22 @@ Gem::Specification.new do |s|
|
|
|
10
10
|
s.authors = ["Aman Gupta", "Jakub Stastny aka botanicus", "Michael S. Klishin"]
|
|
11
11
|
s.homepage = "http://github.com/ruby-amqp/amqp"
|
|
12
12
|
s.summary = "AMQP client implementation in Ruby/EventMachine."
|
|
13
|
-
s.description = "
|
|
13
|
+
s.description = "Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries included"
|
|
14
14
|
s.cert_chain = nil
|
|
15
15
|
s.email = ["bWljaGFlbEBub3ZlbWJlcmFpbi5jb20=\n", "c3Rhc3RueUAxMDFpZGVhcy5jeg==\n"].map { |i| Base64.decode64(i) }
|
|
16
16
|
|
|
17
17
|
# files
|
|
18
|
-
s.files = `git ls-files`.split("\n").reject { |file| file =~ /^vendor\// }
|
|
18
|
+
s.files = `git ls-files`.split("\n").reject { |file| file =~ /^vendor\// || file =~ /^gemfiles\// }
|
|
19
19
|
s.require_paths = ["lib"]
|
|
20
20
|
|
|
21
21
|
# RDoc
|
|
22
22
|
s.has_rdoc = true
|
|
23
23
|
s.rdoc_options = '--include=examples --main README.textile'
|
|
24
|
-
s.extra_rdoc_files = ["README.textile"] + Dir.glob("
|
|
24
|
+
s.extra_rdoc_files = ["README.textile"] + Dir.glob("docs/*")
|
|
25
25
|
|
|
26
26
|
# Dependencies
|
|
27
|
-
s.add_dependency "eventmachine"
|
|
28
|
-
s.add_dependency "amq-client", ">= 0.7.0.
|
|
27
|
+
s.add_dependency "eventmachine"
|
|
28
|
+
s.add_dependency "amq-client", ">= 0.7.0.alpha13"
|
|
29
29
|
|
|
30
30
|
begin
|
|
31
31
|
require "changelog"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
h1. TBD
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
h2. About this guide
|
|
5
|
+
|
|
6
|
+
TBD
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
h2. Covered versions
|
|
10
|
+
|
|
11
|
+
This guide covers amqp gem v0.8.0 and later.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
h2. TBD
|
|
16
|
+
|
|
17
|
+
TBD
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
h2. Tell us what you think!
|
|
22
|
+
|
|
23
|
+
Please take a moment and tell us what you think about this guide on "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp:
|
|
24
|
+
what was unclear? what wasn't covered? maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is
|
|
25
|
+
key to making documentation better.
|
|
26
|
+
|
|
27
|
+
If mailing list communication is not an option for you for some reason, you can "contact guides author directly":mailto:michael@novemberain.com?subject=amqp%20gem%20documentation
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
h1. TBD
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
h2. About this guide
|
|
5
|
+
|
|
6
|
+
TBD
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
h2. Covered versions
|
|
10
|
+
|
|
11
|
+
This guide covers amqp gem v0.8.0 and later.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
h2. TBD
|
|
16
|
+
|
|
17
|
+
TBD
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
h2. Tell us what you think!
|
|
22
|
+
|
|
23
|
+
Please take a moment and tell us what you think about this guide on "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp:
|
|
24
|
+
what was unclear? what wasn't covered? maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is
|
|
25
|
+
key to making documentation better.
|
|
26
|
+
|
|
27
|
+
If mailing list communication is not an option for you for some reason, you can "contact guides author directly":mailto:michael@novemberain.com?subject=amqp%20gem%20documentation
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
h1. Connecting to the broker
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
h2. About this guide
|
|
5
|
+
|
|
6
|
+
This guide covers connection to AMQP broker from standalone and Web applications,
|
|
7
|
+
connection error handling, authentication failure handling and related issues..
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
h2. Covered versions
|
|
11
|
+
|
|
12
|
+
This guide covers amqp gem v0.8.0 and later.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
h2. Terminology
|
|
17
|
+
|
|
18
|
+
In this guide we define standalone application as application that does not run on
|
|
19
|
+
a Web server like Unicorn or Passenger. The key difference is that these applications
|
|
20
|
+
control main Ruby VM thread and often use it to run EventMachine event loop. When
|
|
21
|
+
amqp gem is used inside of a Web applications, main thread is occupied by Web application
|
|
22
|
+
server and code required to establish connection to AMQP broker needs to be a little
|
|
23
|
+
bit different.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
h2. In standalone applications
|
|
28
|
+
|
|
29
|
+
h3. EventMachine event loop
|
|
30
|
+
|
|
31
|
+
amqp gem uses "EventMachine":http://rubyeventmachine.com under the hood and needs EventMachine
|
|
32
|
+
event loop to be running in order to connect to AMQP broker or send any data. This means that
|
|
33
|
+
before connecting to AMQP broker, we need to _start EventMachine reactor_ (get the event loop
|
|
34
|
+
going). Here is how to do it:
|
|
35
|
+
|
|
36
|
+
<pre>
|
|
37
|
+
<code>
|
|
38
|
+
require "amqp"
|
|
39
|
+
|
|
40
|
+
EventMachine.run do
|
|
41
|
+
# ...
|
|
42
|
+
end
|
|
43
|
+
</code>
|
|
44
|
+
</pre>
|
|
45
|
+
|
|
46
|
+
"EventMachine.run":http://eventmachine.rubyforge.org/EventMachine.html#M000461 will block current thread until event loop is stopped.
|
|
47
|
+
Standalone applications often can afford starting event loop on the main thread. If you have no experience with threading, this is a
|
|
48
|
+
recommended way.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
h3. AMQP.connect with a block
|
|
52
|
+
|
|
53
|
+
Once event loop is running, {AMQP.connect} method will attempt to connect to the broker. It can be used in two ways. Here is the
|
|
54
|
+
first one:
|
|
55
|
+
|
|
56
|
+
<pre>
|
|
57
|
+
<code>
|
|
58
|
+
require "amqp"
|
|
59
|
+
|
|
60
|
+
EventMachine.run do
|
|
61
|
+
# using AMQP.connect with a block
|
|
62
|
+
AMQP.connect(:host => "localhost") do |client|
|
|
63
|
+
# connection is open and ready to be used
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
</code>
|
|
67
|
+
</pre>
|
|
68
|
+
|
|
69
|
+
{AMQP.connect} takes a block that will be executed as soon as AMQP connection is open (TCP connection was set up,
|
|
70
|
+
authentication succeeded, broker and client finished negotiating connection parameters like max frame size).
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
h3. AMQP.connect without a callback
|
|
74
|
+
|
|
75
|
+
Alternative way of connecting is this:
|
|
76
|
+
|
|
77
|
+
<pre>
|
|
78
|
+
<code>
|
|
79
|
+
require "amqp"
|
|
80
|
+
|
|
81
|
+
EventMachine.run do
|
|
82
|
+
# using AMQP.connect with a block
|
|
83
|
+
client = AMQP.connect(:host => "hub.megacorp.internal", :username => "hedgehog", :password => "t0ps3kr3t")
|
|
84
|
+
# connection is not yet open, however, amqp gem will delay
|
|
85
|
+
# channel operations until after connection is open. However,
|
|
86
|
+
# amqp gem cannot solve every possible race condition so be careful
|
|
87
|
+
end
|
|
88
|
+
</code>
|
|
89
|
+
</pre>
|
|
90
|
+
|
|
91
|
+
If you do not need to assign returned value to a variable, "block version" is recommended because it eliminates issues that may
|
|
92
|
+
arise from attempts to use a connection object that is not fully opened yet. For example, handling of authentication failures is simpler
|
|
93
|
+
with the block version, as we will see in the following sections.
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
h3. AMQP.start
|
|
97
|
+
|
|
98
|
+
EventMachine.run and {AMQP.connect} with a block is such a common combination that amqp gem provides a shortcut:
|
|
99
|
+
|
|
100
|
+
<pre>
|
|
101
|
+
<code>
|
|
102
|
+
require "amqp"
|
|
103
|
+
|
|
104
|
+
AMQP.start("amqp://dev.rabbitmq.com:5672/") do |client|
|
|
105
|
+
# connection is open and ready to be used
|
|
106
|
+
end
|
|
107
|
+
</code>
|
|
108
|
+
</pre>
|
|
109
|
+
|
|
110
|
+
As these examples demonstrate, {AMQP.connect} and {AMQP.start} accept either a Hash of connection options or a connection URI string.
|
|
111
|
+
See reference documentation for each method to learn all the options they accept and what the default values are.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
h3. On Thread#sleep use
|
|
115
|
+
|
|
116
|
+
When not passing a block to {AMQP.connect}, it is tempting to "give connection some time to get through" by using Thread#sleep. Unless you are
|
|
117
|
+
running event loop in a separate thread, don't do this. Thread#sleep blocks current thread so if event loop is running the very same current thread,
|
|
118
|
+
blocking it _will also block the event loop_. *When event loop is blocked, no data is sent or received, so connection does not proceed.*
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
h3. Detecting TCP connection failures
|
|
122
|
+
|
|
123
|
+
When applications connect to the broker, they need to handle connection failures. Networks are not 100% reliable, even with modern system configuration tools
|
|
124
|
+
like Chef or Puppet misconfigurations happen and broker might be down, too. Error detection should happen as early as possible. There are two ways of detecting
|
|
125
|
+
TCP connection failure, the first one is to catch an exception:
|
|
126
|
+
|
|
127
|
+
<pre>
|
|
128
|
+
<code>
|
|
129
|
+
#!/usr/bin/env ruby
|
|
130
|
+
# encoding: utf-8
|
|
131
|
+
|
|
132
|
+
require "rubygems"
|
|
133
|
+
require "amqp"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
puts "=> TCP connection failure handling with a rescue statement"
|
|
137
|
+
puts
|
|
138
|
+
|
|
139
|
+
connection_settings = {
|
|
140
|
+
:port => 9689,
|
|
141
|
+
:vhost => "/amq_client_testbed",
|
|
142
|
+
:user => "amq_client_gem",
|
|
143
|
+
:password => "amq_client_gem_password",
|
|
144
|
+
:timeout => 0.3
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
begin
|
|
148
|
+
AMQP.start(connection_settings) do |connection, open_ok|
|
|
149
|
+
raise "This should not be reachable"
|
|
150
|
+
end
|
|
151
|
+
rescue AMQP::TCPConnectionFailed => e
|
|
152
|
+
puts "Caught AMQP::TCPConnectionFailed => TCP connection failed, as expected."
|
|
153
|
+
end
|
|
154
|
+
</code>
|
|
155
|
+
</pre>
|
|
156
|
+
|
|
157
|
+
{AMQP.connect} (and, subsequentily, {AMQP.start}) will raise {AMQP::TCPConnectionFailed} if connection fails. Code that catches it can write to log
|
|
158
|
+
about the issue or use retry to execute begin block one more time. Because initial connection failures are due to misconfiguration or network outage, reconnection
|
|
159
|
+
to the same endpoint (hostname, port, vhost combination) will result in the same issue over and over. TBD: failover, connection to the cluster.
|
|
160
|
+
|
|
161
|
+
Alternative way of handling connection failure is with an errback (a callback for specific kind of error):
|
|
162
|
+
|
|
163
|
+
<pre>
|
|
164
|
+
<code>
|
|
165
|
+
#!/usr/bin/env ruby
|
|
166
|
+
# encoding: utf-8
|
|
167
|
+
|
|
168
|
+
require "rubygems"
|
|
169
|
+
require "amqp"
|
|
170
|
+
|
|
171
|
+
puts "=> TCP connection failure handling with a callback"
|
|
172
|
+
puts
|
|
173
|
+
|
|
174
|
+
handler = Proc.new { |settings| puts "Failed to connect, as expected"; EM.stop }
|
|
175
|
+
connection_settings = {
|
|
176
|
+
:port => 9689,
|
|
177
|
+
:vhost => "/amq_client_testbed",
|
|
178
|
+
:user => "amq_client_gem",
|
|
179
|
+
:password => "amq_client_gem_password",
|
|
180
|
+
:timeout => 0.3,
|
|
181
|
+
:on_tcp_connection_failure => handler
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
AMQP.start(connection_settings) do |connection, open_ok|
|
|
186
|
+
raise "This should not be reachable"
|
|
187
|
+
end
|
|
188
|
+
</code>
|
|
189
|
+
</pre>
|
|
190
|
+
|
|
191
|
+
:on_tcp_connection_failure option accepts any object that responds to #call.
|
|
192
|
+
|
|
193
|
+
If you connect to the broker from a code in a class (as opposed to top-level scope in a script), Object#method can be used to pass object method as a handler
|
|
194
|
+
instead of a Proc.
|
|
195
|
+
|
|
196
|
+
TBD: provide an example
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
h3. Detecting authentication failures
|
|
200
|
+
|
|
201
|
+
Another reason why connection may fail is authentication failure. Handling authentication failure is very similar to handling initial TCP
|
|
202
|
+
connection failure:
|
|
203
|
+
|
|
204
|
+
<pre>
|
|
205
|
+
<code>
|
|
206
|
+
#!/usr/bin/env ruby
|
|
207
|
+
# encoding: utf-8
|
|
208
|
+
|
|
209
|
+
require "rubygems"
|
|
210
|
+
require "amqp"
|
|
211
|
+
|
|
212
|
+
puts "=> TCP connection failure handling with a callback"
|
|
213
|
+
puts
|
|
214
|
+
|
|
215
|
+
handler = Proc.new { |settings| puts "Failed to connect, as expected"; EM.stop }
|
|
216
|
+
connection_settings = {
|
|
217
|
+
:port => 5672,
|
|
218
|
+
:vhost => "/amq_client_testbed",
|
|
219
|
+
:user => "amq_client_gem",
|
|
220
|
+
:password => "amq_client_gem_password_that_is_incorrect #{Time.now.to_i}",
|
|
221
|
+
:timeout => 0.3,
|
|
222
|
+
:on_tcp_connection_failure => handler,
|
|
223
|
+
:on_possible_authentication_failure => Proc.new { |settings|
|
|
224
|
+
puts "Authentication failed, as expected, settings are: #{settings.inspect}"
|
|
225
|
+
|
|
226
|
+
EM.stop
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
AMQP.start(connection_settings) do |connection, open_ok|
|
|
231
|
+
raise "This should not be reachable"
|
|
232
|
+
end
|
|
233
|
+
</code>
|
|
234
|
+
</pre>
|
|
235
|
+
|
|
236
|
+
In case you wonder why callback name has "possible" in it: {http://bit.ly/mTr1YN AMQP 0.9.1 spec} requires broker implementations to
|
|
237
|
+
simply close TCP connection without sending any more data when an exception (such as authentication failure) occurs before AMQP connection
|
|
238
|
+
is open. In practice, however, when broker closes TCP connection between successful TCP connection and before AMQP connection is open,
|
|
239
|
+
it means that authentication has failed.
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
h2. In Web applications (Ruby on Rails, Sinatra, Merb, Rack)
|
|
244
|
+
|
|
245
|
+
h3. With Unicorn
|
|
246
|
+
|
|
247
|
+
TBD
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
h3. With Thin
|
|
251
|
+
|
|
252
|
+
TBD
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
h3. With Goliath
|
|
256
|
+
|
|
257
|
+
TBD
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
h3. With Passenger
|
|
261
|
+
|
|
262
|
+
TBD
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
h2. What to read next
|
|
267
|
+
|
|
268
|
+
TBD
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
h2. Tell us what you think!
|
|
272
|
+
|
|
273
|
+
Please take a moment and tell us what you think about this guide on "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp:
|
|
274
|
+
what was unclear? what wasn't covered? maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is
|
|
275
|
+
key to making documentation better.
|
|
276
|
+
|
|
277
|
+
If mailing list communication is not an option for you for some reason, you can "contact guides author directly":mailto:michael@novemberain.com?subject=amqp%20gem%20documentation
|