amqp 0.8.0.rc12 → 0.8.0.rc13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/.travis.yml +1 -1
  2. data/.yardopts +2 -1
  3. data/CONTRIBUTORS +29 -22
  4. data/Gemfile +2 -1
  5. data/README.md +241 -0
  6. data/amqp.gemspec +7 -5
  7. data/bin/set_test_suite_realms_up.sh +6 -6
  8. data/docs/08Migration.textile +3 -1
  9. data/docs/Bindings.textile +3 -1
  10. data/docs/Clustering.textile +4 -0
  11. data/docs/ConnectingToTheBroker.textile +108 -86
  12. data/docs/ConnectionEncryptionWithTLS.textile +3 -1
  13. data/docs/DocumentationGuidesIndex.textile +24 -2
  14. data/docs/Durability.textile +22 -1
  15. data/docs/ErrorHandling.textile +21 -1
  16. data/docs/Exchanges.textile +181 -9
  17. data/docs/GettingStarted.textile +65 -167
  18. data/docs/Queues.textile +400 -355
  19. data/docs/RabbitMQVersions.textile +34 -3
  20. data/docs/Routing.textile +4 -1
  21. data/docs/RunningTests.textile +116 -0
  22. data/docs/Troubleshooting.textile +131 -0
  23. data/docs/VendorSpecificExtensions.textile +20 -0
  24. data/examples/channels/qos_aka_prefetch.rb +3 -3
  25. data/examples/channels/qos_aka_prefetch_without_callback.rb +2 -2
  26. data/examples/error_handling/channel_level_exception.rb +1 -1
  27. data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +1 -0
  28. data/examples/error_handling/connection_level_exception.rb +26 -0
  29. data/examples/error_handling/global_channel_level_exception_handler.rb +3 -3
  30. data/examples/exchanges/autodeletion_of_exchanges.rb +37 -0
  31. data/examples/extensions/rabbitmq/per_queue_message_ttl.rb +3 -3
  32. data/examples/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +2 -2
  33. data/examples/guides/getting_started/{03_babblr.rb → 03_blabbr.rb} +0 -0
  34. data/examples/guides/queues/01a_declaring_a_server_named_queue_using_queue_constructor.rb +18 -0
  35. data/examples/guides/queues/01b_declaring_a_queue_using_queue_constructor.rb +18 -0
  36. data/examples/guides/queues/02a_declaring_a_durable_shared_queue.rb +18 -0
  37. data/examples/guides/queues/02b_declaring_a_durable_shared_queue.rb +18 -0
  38. data/examples/guides/queues/03a_declaring_a_temporary_exclusive_queue.rb +19 -0
  39. data/examples/guides/queues/03b_declaring_a_temporary_exclusive_queue.rb +18 -0
  40. data/examples/guides/queues/{05_binding_a_queue_using_exchange_instance.rb → 04_bind_a_queue_using_exchange_instance.rb} +2 -2
  41. data/examples/guides/queues/{06_biding_a_queue_using_exchange_name_string.rb → 05_bind_a_queue_using_exchange_name.rb} +2 -2
  42. data/examples/guides/queues/{07_subscribing_to_receive_messages.rb → 06_subscribe_to_receive_messages.rb} +1 -1
  43. data/examples/guides/queues/{08_poll_for_messages.rb → 07_fetch_a_message_from_the_queue.rb} +1 -1
  44. data/examples/guides/queues/{09_unsubscribing_a_consumer.rb → 08_unsubscribing_a_consumer.rb} +0 -0
  45. data/examples/guides/queues/{10_unbinding_from_exchange.rb → 09_unbinding_from_exchange.rb} +2 -2
  46. data/examples/guides/queues/{11_purge_a_queue.rb → 10_purge_a_queue.rb} +2 -2
  47. data/examples/guides/queues/{12_deleting_a_queue.rb → 11_deleting_a_queue.rb} +2 -2
  48. data/examples/hello_world.rb +1 -1
  49. data/examples/hello_world_with_an_empty_string.rb +33 -0
  50. data/examples/issues/amq_client_issue_7.rb +31 -0
  51. data/examples/issues/amq_protocol_issue_14.rb +46 -0
  52. data/examples/issues/issue_75.rb +23 -0
  53. data/examples/issues/issue_79.rb +35 -0
  54. data/examples/issues/issue_80.rb +40 -0
  55. data/examples/publishing/{publishing_and_immediately_stopping_event_loop.rb → publishing_a_one_off_message.rb} +9 -12
  56. data/examples/publishing/publishing_callback.rb +52 -0
  57. data/examples/publishing/returned_messages.rb +3 -3
  58. data/examples/queues/accessing_message_metadata.rb +60 -0
  59. data/examples/queues/queue_status.rb +0 -7
  60. data/examples/queues/rejecting_messages_without_requeueuing.rb +47 -0
  61. data/examples/queues/using_explicit_acknowledgements.rb +96 -0
  62. data/examples/routing/headers_routing.rb +54 -0
  63. data/lib/amqp/channel.rb +245 -40
  64. data/lib/amqp/client.rb +23 -11
  65. data/lib/amqp/exchange.rb +58 -41
  66. data/lib/amqp/queue.rb +66 -13
  67. data/lib/amqp/version.rb +1 -1
  68. data/spec/integration/authentication_spec.rb +5 -5
  69. data/spec/integration/basic_get_spec.rb +1 -1
  70. data/spec/integration/channel_close_spec.rb +10 -3
  71. data/spec/integration/queue_declaration_spec.rb +26 -5
  72. data/spec/integration/topic_subscription_spec.rb +1 -1
  73. data/spec/unit/amqp/client_spec.rb +7 -54
  74. data/tasks.rb +1 -8
  75. metadata +64 -23
  76. data/README.textile +0 -229
@@ -1,10 +1,10 @@
1
1
  script: "bundle exec rake spec:ci"
2
2
  rvm:
3
3
  - 1.8.7
4
+ - rbx
4
5
  - 1.9.2
5
6
  - ree
6
7
  - jruby
7
- - rbx
8
8
  gemfile:
9
9
  - Gemfile
10
10
  - gemfiles/eventmachine-pre
data/.yardopts CHANGED
@@ -1,7 +1,8 @@
1
1
  --no-private
2
2
  --protected
3
3
  --markup="textile" lib/**/*.rb
4
- --main README.textile
4
+ --main README.md
5
+ --asset docs:docs --asset examples:examples
5
6
  -
6
7
  LICENSE
7
8
  CHANGELOG
@@ -1,22 +1,29 @@
1
- Aman Gupta: 232
2
- Jakub Šťastný aka Botanicus: 57
3
- arvicco: 26
4
- Michael S. Klishin: 17
5
- Chuck Remes: 7
6
- Marek Majkowski: 4
7
- Chris Van Pelt: 3
8
- Jake Douglas: 3
9
- Doug Barth: 2
10
- coderrr: 2
11
- binary42: 1
12
- Daniel Neighman: 1
13
- Brendan Ribera: 1
14
- dan: 1
15
- Dane Jensen: 1
16
- Tony Garnock-Jones: 1
17
- Phil Smith: 1
18
- Kasper Bjørn Nielsen: 1
19
- Simon Horne: 1
20
- Cliff Moon: 1
21
- Coda Hale: 1
22
- John Richmond: 1
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.0"
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
@@ -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
+ [![Continuous Integration status](http://travis-ci.org/ruby-amqp/amqp.png)](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)
@@ -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 implementation in Ruby/EventMachine."
13
- s.description = "Widely used, feature-rich asynchronous AMQP 0.9.1 client with batteries included"
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.textile'
21
- s.extra_rdoc_files = ["README.textile"] + Dir.glob("docs/*")
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", ">= 0.7.0.alpha25"
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 /amqp_gem_testbed
10
+ # amqp_gem:amqp_gem_password has full access to amqp_gem_testbed
11
11
 
12
- rabbitmqctl add_vhost /amqp_gem_testbed
12
+ rabbitmqctl add_vhost amqp_gem_testbed
13
13
  rabbitmqctl add_user amqp_gem amqp_gem_password
14
- rabbitmqctl set_permissions -p /amqp_gem_testbed amqp_gem ".*" ".*" ".*"
14
+ rabbitmqctl set_permissions -p amqp_gem_testbed amqp_gem ".*" ".*" ".*"
15
15
 
16
16
 
17
- # amqp_gem_reader:reader_password has read access to /amqp_gem_testbed
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 /amqp_gem_testbed guest
21
- rabbitmqctl set_permissions -p /amqp_gem_testbed amqp_gem_reader "^---$" "^---$" ".*"
20
+ rabbitmqctl clear_permissions -p amqp_gem_testbed guest
21
+ rabbitmqctl set_permissions -p amqp_gem_testbed amqp_gem_reader "^---$" "^---$" ".*"
@@ -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
 
@@ -1,3 +1,5 @@
1
+ # @title Ruby AMQP gem: Bindings
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
 
@@ -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
- h1. Connecting to the broker
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 possible to use connection URIs la JDBC) with amqp and amqps schemas, for example:
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
- Two supported schemas are *amqp* and *amqps*. Default port for amqp is 5672. If port isn't given, and schema
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
- h4. Vhosts: naming schemas and parsing
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
- AMQP 0.9.1 spec does not define what vhost naming scheme should be. RabbitMQ and Apache Qpid use different schemes
82
- (Qpid said to have two) but the bottom line is: even though some brokers use / as the default vhost, it can be *any string*.
83
- Host (and optional port) part must be separated from vhost (path component) with a slash character (/).
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 {AMQP::Client.parse_connection_uri} parses out vhost from connection URI:
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///a/b/c/d") # => vhost is //a/b/c/d
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
- Since Unicorn is not EventMachine-based, you need to start EventMachine reactor in a separate thread like this:
375
+ h3. Using Ruby amqp gem with Unicorn
371
376
 
372
- <pre>
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
- # now is a good moment to use AMQP.connect
379
- </code>
380
- </pre>
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
- Otherwise EventMachine will block current thread.
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
- Because *Unicorn is a pre-forking server, you need to run the same piece of code in
387
- after_fork hook in Unicorn configuration file for your app*, otherwise, worker processes won't have EventMachine reactor running:
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
- # example snippet of Unicorn configuration file ( config/unicorn/development.rb or similar)
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
- # now is a good moment to use AMQP.connect
398
- end
399
- </code>
400
- </pre>
397
+ listen 3000
401
398
 
399
+ worker_processes 1
400
+ timeout 30
402
401
 
403
- h3. Using amqp gem with Passenger
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
- h4. Thin and Goliath start EventMachine reactor for you, but there is a little nuance
413
+ t = Thread.new { AMQP.start }
414
+ sleep(1.0)
412
415
 
413
- 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.
414
- 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,
415
- 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:
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
- <pre>
418
- <code>
419
- EventMachine.next_tick { AMQP.connect(...) }
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
- So in case EventMachine reactor isn't running yet on server/application boot, connection won't fail but instead wait for reactor to start.
424
- 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.
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
- * AMQP broker log.
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
- h3. Inspecting AMQP broker log file
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
- In this section we will cover typical problems that can be tracked down by reading AMQP broker log. We will use RabbitMQ as an example, however, different AMQP brokers
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
- Here is what authentication failure looks like in RabbitMQ log:
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
- =ERROR REPORT==== 17-May-2011::17:37:58 ===
454
- exception on TCP connection <0.4770.0> from 127.0.0.1:46551
455
- {channel0_error,starting,
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
- This means that connection attempt with username pipeline_agent failed because credentials were invalid. If you are seeing this message, make sure username,
462
- password *and vhost* are correct.
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
- Means that client supports AMQP 0.9.1 but broker doesn't (RabbitMQ versions pre-2.0 only support AMQP 0.8, for example). If you are using amqp gem 0.8 or later
474
- and seeing this entry in your broker log, you are connecting to AMQP broker that is too old to support this AMQP version. In case of RabbitMQ, make sure you run
475
- version 2.0 or later.
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>