amqp 0.8.0.rc12 → 0.8.0.rc13
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 +1 -1
- data/.yardopts +2 -1
- data/CONTRIBUTORS +29 -22
- data/Gemfile +2 -1
- data/README.md +241 -0
- data/amqp.gemspec +7 -5
- data/bin/set_test_suite_realms_up.sh +6 -6
- data/docs/08Migration.textile +3 -1
- data/docs/Bindings.textile +3 -1
- data/docs/Clustering.textile +4 -0
- data/docs/ConnectingToTheBroker.textile +108 -86
- data/docs/ConnectionEncryptionWithTLS.textile +3 -1
- data/docs/DocumentationGuidesIndex.textile +24 -2
- data/docs/Durability.textile +22 -1
- data/docs/ErrorHandling.textile +21 -1
- data/docs/Exchanges.textile +181 -9
- data/docs/GettingStarted.textile +65 -167
- data/docs/Queues.textile +400 -355
- data/docs/RabbitMQVersions.textile +34 -3
- data/docs/Routing.textile +4 -1
- data/docs/RunningTests.textile +116 -0
- data/docs/Troubleshooting.textile +131 -0
- data/docs/VendorSpecificExtensions.textile +20 -0
- data/examples/channels/qos_aka_prefetch.rb +3 -3
- data/examples/channels/qos_aka_prefetch_without_callback.rb +2 -2
- data/examples/error_handling/channel_level_exception.rb +1 -1
- data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +1 -0
- data/examples/error_handling/connection_level_exception.rb +26 -0
- data/examples/error_handling/global_channel_level_exception_handler.rb +3 -3
- data/examples/exchanges/autodeletion_of_exchanges.rb +37 -0
- data/examples/extensions/rabbitmq/per_queue_message_ttl.rb +3 -3
- data/examples/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +2 -2
- data/examples/guides/getting_started/{03_babblr.rb → 03_blabbr.rb} +0 -0
- data/examples/guides/queues/01a_declaring_a_server_named_queue_using_queue_constructor.rb +18 -0
- data/examples/guides/queues/01b_declaring_a_queue_using_queue_constructor.rb +18 -0
- data/examples/guides/queues/02a_declaring_a_durable_shared_queue.rb +18 -0
- data/examples/guides/queues/02b_declaring_a_durable_shared_queue.rb +18 -0
- data/examples/guides/queues/03a_declaring_a_temporary_exclusive_queue.rb +19 -0
- data/examples/guides/queues/03b_declaring_a_temporary_exclusive_queue.rb +18 -0
- data/examples/guides/queues/{05_binding_a_queue_using_exchange_instance.rb → 04_bind_a_queue_using_exchange_instance.rb} +2 -2
- data/examples/guides/queues/{06_biding_a_queue_using_exchange_name_string.rb → 05_bind_a_queue_using_exchange_name.rb} +2 -2
- data/examples/guides/queues/{07_subscribing_to_receive_messages.rb → 06_subscribe_to_receive_messages.rb} +1 -1
- data/examples/guides/queues/{08_poll_for_messages.rb → 07_fetch_a_message_from_the_queue.rb} +1 -1
- data/examples/guides/queues/{09_unsubscribing_a_consumer.rb → 08_unsubscribing_a_consumer.rb} +0 -0
- data/examples/guides/queues/{10_unbinding_from_exchange.rb → 09_unbinding_from_exchange.rb} +2 -2
- data/examples/guides/queues/{11_purge_a_queue.rb → 10_purge_a_queue.rb} +2 -2
- data/examples/guides/queues/{12_deleting_a_queue.rb → 11_deleting_a_queue.rb} +2 -2
- data/examples/hello_world.rb +1 -1
- data/examples/hello_world_with_an_empty_string.rb +33 -0
- data/examples/issues/amq_client_issue_7.rb +31 -0
- data/examples/issues/amq_protocol_issue_14.rb +46 -0
- data/examples/issues/issue_75.rb +23 -0
- data/examples/issues/issue_79.rb +35 -0
- data/examples/issues/issue_80.rb +40 -0
- data/examples/publishing/{publishing_and_immediately_stopping_event_loop.rb → publishing_a_one_off_message.rb} +9 -12
- data/examples/publishing/publishing_callback.rb +52 -0
- data/examples/publishing/returned_messages.rb +3 -3
- data/examples/queues/accessing_message_metadata.rb +60 -0
- data/examples/queues/queue_status.rb +0 -7
- data/examples/queues/rejecting_messages_without_requeueuing.rb +47 -0
- data/examples/queues/using_explicit_acknowledgements.rb +96 -0
- data/examples/routing/headers_routing.rb +54 -0
- data/lib/amqp/channel.rb +245 -40
- data/lib/amqp/client.rb +23 -11
- data/lib/amqp/exchange.rb +58 -41
- data/lib/amqp/queue.rb +66 -13
- data/lib/amqp/version.rb +1 -1
- data/spec/integration/authentication_spec.rb +5 -5
- data/spec/integration/basic_get_spec.rb +1 -1
- data/spec/integration/channel_close_spec.rb +10 -3
- data/spec/integration/queue_declaration_spec.rb +26 -5
- data/spec/integration/topic_subscription_spec.rb +1 -1
- data/spec/unit/amqp/client_spec.rb +7 -54
- data/tasks.rb +1 -8
- metadata +64 -23
- data/README.textile +0 -229
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/CONTRIBUTORS
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
John Richmond
|
|
1
|
+
557 Michael S. Klishin
|
|
2
|
+
232 Aman Gupta
|
|
3
|
+
98 Jakub Šťastný aka Botanicus
|
|
4
|
+
43 Jakub Stastny aka botanicus
|
|
5
|
+
26 arvicco
|
|
6
|
+
24 Mark Abramov
|
|
7
|
+
7 Chuck Remes
|
|
8
|
+
4 Marek Majkowski
|
|
9
|
+
4 David Wragg
|
|
10
|
+
3 Chris Van Pelt
|
|
11
|
+
3 Jake Douglas
|
|
12
|
+
2 Yuri Leikind
|
|
13
|
+
2 coderrr
|
|
14
|
+
2 Doug Barth
|
|
15
|
+
1 binary42
|
|
16
|
+
1 dan
|
|
17
|
+
1 Brendan Ribera
|
|
18
|
+
1 Cliff Moon
|
|
19
|
+
1 Coda Hale
|
|
20
|
+
1 Dane Jensen
|
|
21
|
+
1 Daniel Neighman
|
|
22
|
+
1 John Richmond
|
|
23
|
+
1 Jonathan Bryant
|
|
24
|
+
1 Jordan Ritter
|
|
25
|
+
1 Kasper Bjørn Nielsen
|
|
26
|
+
1 Michael
|
|
27
|
+
1 Phil Smith
|
|
28
|
+
1 Simon Horne
|
|
29
|
+
1 Tony Garnock-Jones
|
data/Gemfile
CHANGED
|
@@ -19,9 +19,10 @@ custom_gem "amq-client", :git => "git://github.com/ruby-amqp/amq-client.git",
|
|
|
19
19
|
custom_gem "amq-protocol", :git => "git://github.com/ruby-amqp/amq-protocol.git", :branch => "master"
|
|
20
20
|
|
|
21
21
|
group(:development) do
|
|
22
|
-
gem "yard", ">= 0.7.
|
|
22
|
+
gem "yard", ">= 0.7.1"
|
|
23
23
|
# yard tags this buddy along
|
|
24
24
|
gem "RedCloth"
|
|
25
|
+
gem "rdiscount"
|
|
25
26
|
|
|
26
27
|
custom_gem "nake", :platform => :ruby_19
|
|
27
28
|
custom_gem "contributors", :platform => :ruby_19
|
data/README.md
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# About Ruby amqp gem #
|
|
2
|
+
|
|
3
|
+
Ruby amqp gem is a widely used, feature-rich, well-maintained asynchronous AMQP 0.9.1 client with batteries included.
|
|
4
|
+
This library works with Ruby 1.8.7 (p174 and p334), Ruby 1.9.2, [JRuby](http://jruby.org) (highly recommended to Microsoft Windows users), [REE](http://www.rubyenterpriseedition.com) and [Rubinius](http://rubini.us), and is licensed under the [Ruby License](http://www.ruby-lang.org/en/LICENSE.txt)
|
|
5
|
+
|
|
6
|
+
Versions 0.8.0 and later of amqp gem implement [AMQP 0.9.1](http://bit.ly/hw2ELX) and supports [RabbitMQ extensions to AMQP 0.9.1](http://www.rabbitmq.com/extensions.html).
|
|
7
|
+
|
|
8
|
+
[](http://travis-ci.org/ruby-amqp/amqp)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## I know what AMQP is, how do I get started? ##
|
|
12
|
+
|
|
13
|
+
See [Getting started with amqp gem](http://bit.ly/getting-started-with-amqp-ruby-gem) and other [documentation guides](http://bit.ly/amqp-gem-docs).
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## What is AMQP? ##
|
|
18
|
+
|
|
19
|
+
AMQP is an [open standard for messaging middleware](http://www.amqp.org/confluence/display/AMQP/About+AMQP) that
|
|
20
|
+
emphasizes interoperability between different technologies (for example, Java, .NET, Ruby, Python, Node.js, Erlang, C and so on).
|
|
21
|
+
|
|
22
|
+
Key features of AMQP are very flexible yet simple routing and binary protocol efficiency. AMQP supports many sophisticated features, for example,
|
|
23
|
+
message acknowledgements, returning messages to producer, delivery confirmation, flow control and so on.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## What is amqp gem good for? ##
|
|
27
|
+
|
|
28
|
+
One can use amqp gem to make Ruby applications interoperate with other
|
|
29
|
+
applications (both Ruby and not). Complexity and size may vary from
|
|
30
|
+
simple work queues to complex multi-stage data processing workflows that involve
|
|
31
|
+
dozens or hundreds of applications built with all kinds of technologies.
|
|
32
|
+
|
|
33
|
+
Specific examples:
|
|
34
|
+
|
|
35
|
+
* A Web application may route messages to a Java app that works
|
|
36
|
+
with SMS delivery gateways.
|
|
37
|
+
|
|
38
|
+
* Periodically run (Cron-driven) application may notify other systems that
|
|
39
|
+
there are some new results.
|
|
40
|
+
|
|
41
|
+
* Content aggregators may update full-text search and geospatial search indexes
|
|
42
|
+
by delegating actual indexing work to other applications over AMQP.
|
|
43
|
+
|
|
44
|
+
* Companies may provide streaming/push APIs to their customers, partners
|
|
45
|
+
or just general public.
|
|
46
|
+
|
|
47
|
+
* A new shiny Ruby-based system may be integrated with an existing C++-based component
|
|
48
|
+
using AMQP.
|
|
49
|
+
|
|
50
|
+
* An application that watches updates from a real-time stream (be it markets data
|
|
51
|
+
or Twitter stream) can propagate updates to interested parties, including
|
|
52
|
+
Web applications that display that information in the real time.
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
## Getting started with Ruby amqp gem ##
|
|
57
|
+
|
|
58
|
+
### Install RabbitMQ ###
|
|
59
|
+
|
|
60
|
+
Please refer to the [RabbitMQ installation guide](http://www.rabbitmq.com/install.html). Note that for Ubuntu and Debian we strongly advice that you
|
|
61
|
+
use [RabbitMQ apt repository](http://www.rabbitmq.com/debian.html#apt) that has recent versions of RabbitMQ. RabbitMQ packages Ubuntu and Debian ship
|
|
62
|
+
with are outdated even in recent (10.10) releases. Learn more in the [RabbitMQ versions guide](http://rubydoc.info/github/ruby-amqp/amqp/master/file/docs/RabbitMQVersions.textile).
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Install the gem ###
|
|
66
|
+
|
|
67
|
+
On Microsoft Windows 7
|
|
68
|
+
|
|
69
|
+
gem install eventmachine --pre
|
|
70
|
+
gem install amqp --pre --version "~> 0.8.0.RC12"
|
|
71
|
+
|
|
72
|
+
On other OSes or [JRuby](http://jruby.org):
|
|
73
|
+
|
|
74
|
+
gem install amqp --pre --version "~> 0.8.0.RC12"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### "Hello, World" example ###
|
|
78
|
+
|
|
79
|
+
#!/usr/bin/env ruby
|
|
80
|
+
# encoding: utf-8
|
|
81
|
+
|
|
82
|
+
require "rubygems"
|
|
83
|
+
# or
|
|
84
|
+
#
|
|
85
|
+
# require "bundler"
|
|
86
|
+
# Bundler.setup
|
|
87
|
+
#
|
|
88
|
+
# if you use Bundler
|
|
89
|
+
|
|
90
|
+
require 'amqp'
|
|
91
|
+
|
|
92
|
+
EventMachine.run do
|
|
93
|
+
connection = AMQP.connect(:host => '127.0.0.1')
|
|
94
|
+
puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
|
|
95
|
+
|
|
96
|
+
channel = AMQP::Channel.new(connection)
|
|
97
|
+
queue = channel.queue("amqpgem.examples.hello_world", :auto_delete => true)
|
|
98
|
+
exchange = channel.direct("")
|
|
99
|
+
|
|
100
|
+
queue.subscribe do |payload|
|
|
101
|
+
puts "Received a message: #{payload}. Disconnecting..."
|
|
102
|
+
|
|
103
|
+
connection.close {
|
|
104
|
+
EventMachine.stop { exit }
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
exchange.publish "Hello, world!", :routing_key => queue.name
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
[Getting started guide](http://bit.ly/getting-started-with-amqp-ruby-gem) explains this and two more examples in detail,
|
|
113
|
+
and is written in a form of a tutorial.
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Documentation: tutorials, guides & API reference ##
|
|
118
|
+
|
|
119
|
+
We believe that in order to be a library our users **really** love, we need to care about documentation as much as (or more)
|
|
120
|
+
code readability, API beauty and autotomated testing across 5 Ruby implementations on multiple operating systems. We do care
|
|
121
|
+
about our documentation: **if you don't find your answer in documentation, we consider it a high severity bug** that you
|
|
122
|
+
should [file to us](http://github.com/ruby-amqp/amqp/issues). Or just complain to [@rubyamqp](https://twitter.com/rubyamqp) on Twitter.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### Tutorials ###
|
|
126
|
+
|
|
127
|
+
[Getting started guide](http://bit.ly/getting-started-with-amqp-ruby-gem) is written as a tutorial that walks you through
|
|
128
|
+
3 examples:
|
|
129
|
+
|
|
130
|
+
* The "Hello, world" of messaging, 1-to-1 communication
|
|
131
|
+
* Blabbr, a Twitter-like example of broadcasting (1-to-many communication)
|
|
132
|
+
* Weathr, an example of sophisticated routing capabilities AMQP 0.9.1 has to offer (1-to-many or many-to-many communication)
|
|
133
|
+
|
|
134
|
+
all in under 20 minutes. Check it out! If something isn't clear, every guide explains how to contact documentation authors at the bottom
|
|
135
|
+
of the page.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
### Examples ###
|
|
139
|
+
|
|
140
|
+
You can find many examples (both real-world cases and simple demonstrations) under [examples directory](https://github.com/ruby-amqp/amqp/tree/master/examples) in the repository.
|
|
141
|
+
Note that those examples are written against version 0.8.0.rc1 and later. 0.6.x and 0.7.x may not support certain AMQP protocol or "DSL syntax" features.
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
### Documentation guides ###
|
|
145
|
+
|
|
146
|
+
[Documentation guides](http://bit.ly/amqp-gem-docs) describe the library itself as well as AMQP usage scenarios, topics like routing, error handing & recovery, broker-specific extensions, TLS support, troubleshooting and so on.
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
### API reference ###
|
|
150
|
+
|
|
151
|
+
[API reference](http://bit.ly/mDm1JE) is up on [rubydoc.info](http://rubydoc.info) and is updated daily.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
## How to use AMQP gem with Ruby on Rails, Merb, Sinatra and other web frameworks ##
|
|
157
|
+
|
|
158
|
+
We cover this subject for multiple Ruby application servers in [Connecting to the broker guide](http://bit.ly/kFCVQU), take a look and let us know
|
|
159
|
+
what wasn't clear.
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
## Community
|
|
164
|
+
|
|
165
|
+
* Join [Ruby AMQP mailing list](http://groups.google.com/group/ruby-amqp)
|
|
166
|
+
* Follow [@rubyamqp](https://twitter.com/rubyamqp) on Twitter for Ruby AMQP ecosystem updates.
|
|
167
|
+
* Join also [RabbitMQ mailing list](https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss) (AMQP community epicenter).
|
|
168
|
+
* Stop by #rabbitmq on irc.freenode.net. You can use [Web IRC client](http://webchat.freenode.net?channels=rabbitmq) if you don't have an IRC client installed.
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
## Links ##
|
|
173
|
+
|
|
174
|
+
* [API reference](http://rdoc.info/github/ruby-amqp/amqp/master/frames)
|
|
175
|
+
* [Documentation guides](http://bit.ly/amqp-gem-docs)
|
|
176
|
+
* [Code Examples](https://github.com/ruby-amqp/amq-protocol/tree/master/examples/)
|
|
177
|
+
* [Issue tracker](http://github.com/ruby-amqp/amqp/issues)
|
|
178
|
+
* [Continous integration status](http://travis-ci.org/#!/ruby-amqp/amqp)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
## License ##
|
|
182
|
+
|
|
183
|
+
AMQP gem is licensed under the [Ruby License](http://www.ruby-lang.org/en/LICENSE.txt).
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
## Credits and copyright information ##
|
|
188
|
+
|
|
189
|
+
* The Original Code is [tmm1/amqp](http://github.com/tmm1/amqp).
|
|
190
|
+
* The Initial Developer of the Original Code is Aman Gupta.
|
|
191
|
+
* Copyright (c) 2008 - 2010 [Aman Gupta](http://github.com/tmm1).
|
|
192
|
+
* Contributions from [Jakub Stastny](http://github.com/botanicus) are Copyright (c) 2011 VMware, Inc.
|
|
193
|
+
* Copyright (c) 2010 — 2011 [ruby-amqp](https://github.com/ruby-amqp) group members.
|
|
194
|
+
|
|
195
|
+
Currently maintained by [ruby-amqp](https://github.com/ruby-amqp) group members
|
|
196
|
+
Special thanks to Dmitriy Samovskiy, Ben Hood and Tony Garnock-Jones.
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
## How can I learn more about AMQP and messaging in general? ##
|
|
200
|
+
|
|
201
|
+
### AMQP resources ###
|
|
202
|
+
|
|
203
|
+
* [RabbitMQ tutorials](http://www.rabbitmq.com/getstarted.html) that demonstrate interoperability
|
|
204
|
+
* [Wikipedia page on AMQP](http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol)
|
|
205
|
+
* [AMQP quick reference](http://www.rabbitmq.com/amqp-0-9-1-quickref.html)
|
|
206
|
+
* John O'Hara on the [history of AMQP](http://www.acmqueue.org/modules.php?name=Content&pa=showpage&pid=485)
|
|
207
|
+
|
|
208
|
+
### Messaging and distributed systems resources ###
|
|
209
|
+
|
|
210
|
+
* [Enterprise Integration Patterns](http://www.eaipatterns.com), a book about messaging and use of messaging in systems integration.
|
|
211
|
+
|
|
212
|
+
* [A Critique of the Remote Procedure Call Paradigm](http://www.cs.vu.nl/~ast/publications/euteco-1988.pdf)
|
|
213
|
+
* [A Note on Distributed Computing](http://research.sun.com/techrep/1994/smli_tr-94-29.pdf)
|
|
214
|
+
* [Convenience Over Correctness](http://steve.vinoski.net/pdf/IEEE-Convenience_Over_Correctness.pdf)
|
|
215
|
+
* Joe Armstrong on [Erlang messaging vs RPC](http://armstrongonsoftware.blogspot.com/2008/05/road-we-didnt-go-down.html)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
## (Very) Short FAQ ##
|
|
220
|
+
|
|
221
|
+
### So, does amqp gem only work with RabbitMQ? ###
|
|
222
|
+
|
|
223
|
+
This library is developed and tested primarily with [RabbitMQ](http://rabbitmq.com), although it should be compatible with any
|
|
224
|
+
server implementing the [AMQP 0.9.1 spec](http://bit.ly/hw2ELX). For AMQP 0.8 brokers, use amqp gem version 0.7.x.
|
|
225
|
+
|
|
226
|
+
### Why isn't Ruby 1.8.7.-p249 supported? ###
|
|
227
|
+
|
|
228
|
+
Because there is absolutely no way we can both make code like the following (pseudo-synchronous) work
|
|
229
|
+
|
|
230
|
+
conn = AMQP.connect
|
|
231
|
+
ch = AMQP::Channel.new(conn)
|
|
232
|
+
|
|
233
|
+
ex = ch.default_exchange
|
|
234
|
+
ex.publish(some_data)
|
|
235
|
+
|
|
236
|
+
and not be affected by this [Ruby 1.8.7-p249-specific bug (super called outside of method)](http://bit.ly/iONBmH)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
### How does amqp gem relate to amq-client gem, amq-protocol and libraries like bunny? ###
|
|
240
|
+
|
|
241
|
+
See [this page about AMQP gems family](https://github.com/ruby-amqp/amq-client/blob/master/README.textile)
|
data/amqp.gemspec
CHANGED
|
@@ -9,20 +9,22 @@ Gem::Specification.new do |s|
|
|
|
9
9
|
s.version = AMQP::VERSION
|
|
10
10
|
s.authors = ["Aman Gupta", "Jakub Stastny aka botanicus", "Michael S. Klishin"]
|
|
11
11
|
s.homepage = "http://github.com/ruby-amqp/amqp"
|
|
12
|
-
s.summary = "AMQP client
|
|
13
|
-
|
|
12
|
+
s.summary = "Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries included"
|
|
13
|
+
# RubyGems will emit warnings if summary is the same as description. I have no idea why but lets trick it. MK.
|
|
14
|
+
s.description = "Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries included."
|
|
14
15
|
s.email = ["bWljaGFlbEBub3ZlbWJlcmFpbi5jb20=\n", "c3Rhc3RueUAxMDFpZGVhcy5jeg==\n"].map { |i| Base64.decode64(i) }
|
|
15
16
|
|
|
16
17
|
# files
|
|
17
18
|
s.files = `git ls-files`.split("\n").reject { |file| file =~ /^vendor\// || file =~ /^gemfiles\// }
|
|
18
19
|
s.require_paths = ["lib"]
|
|
19
20
|
|
|
20
|
-
s.rdoc_options = '--include=examples --main README.
|
|
21
|
-
s.extra_rdoc_files = ["README.
|
|
21
|
+
s.rdoc_options = '--include=examples --main README.md'
|
|
22
|
+
s.extra_rdoc_files = ["README.md"] + Dir.glob("docs/*")
|
|
22
23
|
|
|
23
24
|
# Dependencies
|
|
24
25
|
s.add_dependency "eventmachine"
|
|
25
|
-
s.add_dependency "amq-client",
|
|
26
|
+
s.add_dependency "amq-client", ">= 0.7.0.alpha34"
|
|
27
|
+
s.add_dependency "amq-protocol", ">= 0.7.0.alpha6"
|
|
26
28
|
|
|
27
29
|
begin
|
|
28
30
|
require "changelog"
|
|
@@ -7,15 +7,15 @@ rabbitmqctl add_user guest guest
|
|
|
7
7
|
rabbitmqctl set_permissions -p / guest ".*" ".*" ".*"
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
# amqp_gem:amqp_gem_password has full access to
|
|
10
|
+
# amqp_gem:amqp_gem_password has full access to amqp_gem_testbed
|
|
11
11
|
|
|
12
|
-
rabbitmqctl add_vhost
|
|
12
|
+
rabbitmqctl add_vhost amqp_gem_testbed
|
|
13
13
|
rabbitmqctl add_user amqp_gem amqp_gem_password
|
|
14
|
-
rabbitmqctl set_permissions -p
|
|
14
|
+
rabbitmqctl set_permissions -p amqp_gem_testbed amqp_gem ".*" ".*" ".*"
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
# amqp_gem_reader:reader_password has read access to
|
|
17
|
+
# amqp_gem_reader:reader_password has read access to amqp_gem_testbed
|
|
18
18
|
|
|
19
19
|
rabbitmqctl add_user amqp_gem_reader reader_password
|
|
20
|
-
rabbitmqctl clear_permissions -p
|
|
21
|
-
rabbitmqctl set_permissions -p
|
|
20
|
+
rabbitmqctl clear_permissions -p amqp_gem_testbed guest
|
|
21
|
+
rabbitmqctl set_permissions -p amqp_gem_testbed amqp_gem_reader "^---$" "^---$" ".*"
|
data/docs/08Migration.textile
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# @title Ruby AMQP gem: Migrating to version 0.8.0 and later
|
|
2
|
+
|
|
1
3
|
h1. TBD
|
|
2
4
|
|
|
3
5
|
|
|
@@ -8,7 +10,7 @@ TBD
|
|
|
8
10
|
|
|
9
11
|
h2. Covered versions
|
|
10
12
|
|
|
11
|
-
This guide covers amqp gem v0.8.0 and later.
|
|
13
|
+
This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0 and later.
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
|
data/docs/Bindings.textile
CHANGED
data/docs/Clustering.textile
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# @title Ruby AMQP gem: Clustering
|
|
2
|
+
|
|
1
3
|
h1. Clustering
|
|
2
4
|
|
|
3
5
|
|
|
@@ -8,6 +10,8 @@ This guide covers clustered AMQP broker setups, with RabbitMQ as example.
|
|
|
8
10
|
|
|
9
11
|
h2. Covered versions
|
|
10
12
|
|
|
13
|
+
This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.9.0 and later.
|
|
14
|
+
|
|
11
15
|
TBD
|
|
12
16
|
|
|
13
17
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# @title Ruby amqp gem: Connecting to the broker, integrating with Ruby on Rails, Merb and Sinatra
|
|
2
|
+
|
|
3
|
+
h1. Connecting to the broker, integrating with Ruby on Rails, Merb and Sinatra
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
h2. About this guide
|
|
5
7
|
|
|
6
8
|
This guide covers connection to AMQP broker from standalone and Web applications,
|
|
7
|
-
connection error handling, authentication failure handling and related issues
|
|
9
|
+
connection error handling, authentication failure handling and related issues.
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
h2. Covered versions
|
|
11
13
|
|
|
12
|
-
This guide covers amqp gem v0.8.0 and later.
|
|
14
|
+
This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0 and later.
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
|
|
@@ -65,42 +67,47 @@ Default connection parameters are
|
|
|
65
67
|
|
|
66
68
|
h3. Using connection strings
|
|
67
69
|
|
|
68
|
-
It is
|
|
70
|
+
It is convenient to be able to specify the AMQP connection
|
|
71
|
+
parameters as a URI string, and various "amqp" URI schemes
|
|
72
|
+
exist. Unfortunately, there is no standard for these URIs, so
|
|
73
|
+
while the schemes share the basic idea, they differ in some
|
|
74
|
+
details. This implementation aims to encourage URIs that work
|
|
75
|
+
as widely as possible.
|
|
76
|
+
|
|
77
|
+
Here are some examples:
|
|
69
78
|
|
|
70
79
|
* amqp://dev.rabbitmq.com
|
|
71
80
|
* amqp://dev.rabbitmq.com:5672
|
|
72
81
|
* amqp://guest:guest@dev.rabbitmq.com:5672
|
|
73
82
|
* amqp://hedgehog:t0ps3kr3t@hub.megacorp.internal/production
|
|
74
|
-
* amqps://hub.megacorp.internal
|
|
83
|
+
* amqps://hub.megacorp.internal/%2Fvault
|
|
75
84
|
|
|
76
|
-
|
|
77
|
-
is amqps, amqp gem will assume it has to connect to 5671, default port for amqps.
|
|
85
|
+
The URI scheme should be "amqp", or "amqps" if SSL is required.
|
|
78
86
|
|
|
79
|
-
|
|
87
|
+
The host, port, username and password are represented in the
|
|
88
|
+
authority component of the URI in the same way as in http URIs.
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
The vhost is obtained from the first segment of the path, with the
|
|
91
|
+
leading slash removed. The path should contain only a single segment
|
|
92
|
+
(i.e, the only slash in it should be the leading one). If the vhost
|
|
93
|
+
is to include slashes or other reserved URI characters, these should
|
|
94
|
+
be percent-escaped.
|
|
84
95
|
|
|
85
|
-
Here are some examples that demonstrate how
|
|
96
|
+
Here are some examples that demonstrate how
|
|
97
|
+
{AMQP::Client.parse_connection_uri} parses out the vhost from
|
|
98
|
+
connection URIs:
|
|
86
99
|
|
|
87
100
|
<pre>
|
|
88
101
|
<code>
|
|
89
102
|
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com") # => vhost is nil, so default (/) will be used
|
|
90
103
|
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/") # => vhost is an empty string
|
|
91
|
-
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//") # => vhost is /
|
|
92
|
-
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//vault") # => vhost is /vault
|
|
93
104
|
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/%2Fvault") # => vhost is /vault
|
|
94
105
|
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/production") # => vhost is production
|
|
95
106
|
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/a.b.c") # => vhost is a.b.c
|
|
96
|
-
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com
|
|
107
|
+
AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/foo/bar") # => ArgumentError
|
|
97
108
|
</code>
|
|
98
109
|
</pre>
|
|
99
110
|
|
|
100
|
-
{AMQP::Client.parse_connection_uri} will also unescape path part of the URI.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
111
|
|
|
105
112
|
h2. Starting event loop & connecting in standalone applications
|
|
106
113
|
|
|
@@ -363,116 +370,112 @@ For Sinatra and pure Rack applications, place it next to other configuration cod
|
|
|
363
370
|
|
|
364
371
|
Next we are going to discuss issues specific to particular Web servers.
|
|
365
372
|
|
|
366
|
-
h3. Using amqp gem with Unicorn
|
|
367
373
|
|
|
368
|
-
h4. Use separate thread for EventMachine reactor
|
|
369
374
|
|
|
370
|
-
|
|
375
|
+
h3. Using Ruby amqp gem with Unicorn
|
|
371
376
|
|
|
372
|
-
|
|
373
|
-
<code>
|
|
374
|
-
Thread.new { EventMachine.run }
|
|
375
|
-
# give EventMachine reactor a moment to start
|
|
376
|
-
sleep(0.5)
|
|
377
|
+
h4. Unicorn is a pre-forking server
|
|
377
378
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
"Unicorn":http://unicorn.bogomips.org is a pre-forking server. That means it forks worker processes that serve HTTP requests. The "fork(2)":http://en.wikipedia.org/wiki/Fork_(operating_system) system call
|
|
380
|
+
has several gotchas associated with it, two of which affect EventMachine and "Ruby amqp gem":http://github.com/ruby-amqp/amqp:
|
|
381
|
+
|
|
382
|
+
* Unintentional file descriptor sharing
|
|
383
|
+
* The fact that "forked child process only inherits one thread":http://bit.ly/fork-and-threads (and EventMachine thread thus is not inherited)
|
|
381
384
|
|
|
382
|
-
|
|
385
|
+
To avoid both problems, start EventMachine reactor and AMQP connection *after* master process forks workers. Master Unicorn process never serves HTTP requests and usually
|
|
386
|
+
doesn't need to hold an AMQP connection. Next lets see how to spin up EventMachine reactor and connect to the broker after Unicorn forks a worker.
|
|
383
387
|
|
|
384
|
-
h4. Starting EventMachine reactor after Unicorn forks worker processes
|
|
385
388
|
|
|
386
|
-
|
|
387
|
-
|
|
389
|
+
h4. Starting EventMachine reactor and connecting to the broker after Unicorn forks worker processes
|
|
390
|
+
|
|
391
|
+
Unicorn lets you specify a configuration file to use. In that file, you define a callback Unicorn runs after it forks worker process(es):
|
|
388
392
|
|
|
389
393
|
<pre>
|
|
390
394
|
<code>
|
|
391
|
-
|
|
392
|
-
after_fork do |server, worker|
|
|
393
|
-
Thread.new { EventMachine.run }
|
|
394
|
-
# give EventMachine reactor a moment to start
|
|
395
|
-
sleep(0.5)
|
|
395
|
+
ENV["FORKING"] = "true"
|
|
396
396
|
|
|
397
|
-
|
|
398
|
-
end
|
|
399
|
-
</code>
|
|
400
|
-
</pre>
|
|
397
|
+
listen 3000
|
|
401
398
|
|
|
399
|
+
worker_processes 1
|
|
400
|
+
timeout 30
|
|
402
401
|
|
|
403
|
-
|
|
402
|
+
preload_app true
|
|
404
403
|
|
|
405
|
-
TBD: if you are a Passenger user, please help us write this section!
|
|
406
404
|
|
|
405
|
+
after_fork do |server, worker|
|
|
406
|
+
require "amqp"
|
|
407
407
|
|
|
408
|
+
# the following is *required* for Rails + "preload_app true",
|
|
409
|
+
defined?(ActiveRecord::Base) and
|
|
410
|
+
ActiveRecord::Base.establish_connection
|
|
408
411
|
|
|
409
|
-
h3. Using amqp gem with Thin and Goliath
|
|
410
412
|
|
|
411
|
-
|
|
413
|
+
t = Thread.new { AMQP.start }
|
|
414
|
+
sleep(1.0)
|
|
412
415
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
+
EventMachine.next_tick do
|
|
417
|
+
AMQP.channel ||= AMQP::Channel.new(AMQP.connection)
|
|
418
|
+
AMQP.channel.queue("amqpgem.examples.rails23.warmup", :durable => true)
|
|
416
419
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
+
3.times do |i|
|
|
421
|
+
puts "[after_fork/amqp] Publishing a warmup message ##{i}"
|
|
422
|
+
|
|
423
|
+
AMQP.channel.default_exchange.publish("A warmup message #{i} from #{Time.now.strftime('%H:%M:%S %m/%b/%Y')}", :routing_key => "amqpgem.examples.rails23.warmup")
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
end
|
|
420
427
|
</code>
|
|
421
428
|
</pre>
|
|
422
429
|
|
|
423
|
-
|
|
424
|
-
|
|
430
|
+
In the example above we start EventMachine reactor in a separate thread, block current thread for 1 second to let event loop spin up and then
|
|
431
|
+
connect to AMQP broker on the next event loop tick. Publishing several warmup messages on boot is a good idea because it
|
|
432
|
+
lets you detect issues that forking may cause earlier.
|
|
425
433
|
|
|
434
|
+
Note that configuration file can easily be used in development environments: other than the fact that Unicorn runs in the foreground,
|
|
435
|
+
it gives you exactly the same application boot behavior as in QA and production environments, which is a good thing.
|
|
426
436
|
|
|
437
|
+
An "example Ruby on Rails application that uses Ruby amqp gem and Unicorn":http://bit.ly/ruby-amqp-gem-example-with-ruby-on-rails-and-unicorn is available on GitHub.
|
|
427
438
|
|
|
428
439
|
|
|
429
|
-
h2. If it just doesn't work: troubleshooting
|
|
430
440
|
|
|
431
|
-
If you read this guide yet your issue is still unresolved, check the following things before asking on the mailing list:
|
|
432
441
|
|
|
433
|
-
|
|
434
|
-
* List of users in a particular vhost you are trying to connect
|
|
435
|
-
* Network connectivity. We know, it's obvious, yet even experienced developers and devops engineers struggle with network access misconfigurations every once in a while.
|
|
436
|
-
* If EventMachine is started in a separate thread, make sure that isn't dead. If it is, this usually means there was an exception that caused it to terminate.
|
|
442
|
+
h3. Using Ruby amqp gem with Passenger
|
|
437
443
|
|
|
444
|
+
Phusion Passenger is a pre-forking server, much like Unicorn. Just like with Unicorn, EventMachine reactor and AMQP connection should be started *after* it forks worker
|
|
445
|
+
processes. Passenger documentation has "a section":http://bit.ly/passenger-forking-gotchas that explains how to avoid problems related to the behavior of fork(2) system
|
|
446
|
+
call, namely:
|
|
438
447
|
|
|
439
|
-
|
|
448
|
+
* Unintentional file descriptor sharing
|
|
449
|
+
* The fact that "forked child process only inherits one thread":http://bit.ly/fork-and-threads (and EventMachine thread thus is not inherited)
|
|
440
450
|
|
|
441
|
-
|
|
442
|
-
often log most of the same issues.
|
|
451
|
+
TBD: if you are a Passenger user, please help us write the rest of this section!
|
|
443
452
|
|
|
444
|
-
RabbitMQ logs abrupt TCP connection failures, timeouts, protocol version mismatches and so on.
|
|
445
|
-
If you are running RabbitMQ, log locations for various operating systems and distributions is documented in the "RabbitMQ installation guide":http://www.rabbitmq.com/install.html
|
|
446
453
|
|
|
447
|
-
On Mac OS X, RabbitMQ installed via Homebrew logs to $HOMEBREW_HOME/var/log/rabbitmq/rabbit@$HOSTNAME.log. For example, if you have Homebrew installed at /usr/local and
|
|
448
|
-
your hostname is giove, log will be at /usr/local/var/log/rabbitmq/rabbit@giove.log.
|
|
449
454
|
|
|
450
|
-
|
|
455
|
+
h3. Using Ruby amqp gem with Thin and Goliath
|
|
456
|
+
|
|
457
|
+
h4. Thin and Goliath start EventMachine reactor for you, but there is a little nuance
|
|
458
|
+
|
|
459
|
+
If you use "Thin":http://code.macournoyer.com/thin/ or "Goliath":https://github.com/postrank-labs/goliath/, you are all set: those two servers use EventMachine under the hood.
|
|
460
|
+
There is no need to start EventMachine reactor. However, depending on app server, it's version, version of the framework and Rack middleware being used,
|
|
461
|
+
EventMachine reactor start may be slightly delayed. To not depend on this factor, use EventMachine.next_tick to delay connection until after reactor is actually running:
|
|
451
462
|
|
|
452
463
|
<pre>
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
{amqp_error,access_refused,
|
|
457
|
-
"AMQPLAIN login refused: user 'pipeline_agent' - invalid credentials",
|
|
458
|
-
'connection.start_ok'}}
|
|
464
|
+
<code>
|
|
465
|
+
EventMachine.next_tick { AMQP.connect(...) }
|
|
466
|
+
</code>
|
|
459
467
|
</pre>
|
|
460
468
|
|
|
461
|
-
|
|
462
|
-
|
|
469
|
+
So in case EventMachine reactor isn't running yet on server/application boot, connection won't fail but instead wait for reactor to start.
|
|
470
|
+
Thin and Goliath are not pre-forking servers so there is no need to re-establish connection the way you do it with Unicorn and Passenger.
|
|
463
471
|
|
|
464
472
|
|
|
465
|
-
The following entry:
|
|
466
473
|
|
|
467
|
-
<pre>
|
|
468
|
-
=ERROR REPORT==== 17-May-2011::17:26:28 ===
|
|
469
|
-
exception on TCP connection <0.4201.62> from 10.8.0.30:57990
|
|
470
|
-
{bad_header,<<65,77,81,80,0,0,9,1>>}
|
|
471
|
-
</pre>
|
|
472
474
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
475
|
+
h2. If it just doesn't work: troubleshooting
|
|
476
|
+
|
|
477
|
+
If you read this guide yet your issue is still unresolved, check our {file:docs/Troubleshooting.textile Troubleshooting guide} before asking on the mailing list
|
|
478
|
+
|
|
476
479
|
|
|
477
480
|
|
|
478
481
|
|
|
@@ -490,3 +493,22 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
|
|
|
490
493
|
key to making documentation better.
|
|
491
494
|
|
|
492
495
|
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
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
<div id="disqus_thread"></div>
|
|
500
|
+
<script type="text/javascript">
|
|
501
|
+
/* * * CONFIGURATION VARIABLES * * */
|
|
502
|
+
var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
|
|
503
|
+
|
|
504
|
+
var disqus_developer = 0; // set to 1 on local machine for testing comments
|
|
505
|
+
var disqus_identifier = 'amqp_connecting_to_the_broker';
|
|
506
|
+
var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/ConnectingToTheBroker.textile';
|
|
507
|
+
|
|
508
|
+
/* * * DON'T EDIT BELOW THIS LINE * * */
|
|
509
|
+
(function() {
|
|
510
|
+
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
|
511
|
+
dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
|
|
512
|
+
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
|
513
|
+
})();
|
|
514
|
+
</script>
|