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,3 +1,5 @@
1
+ # @title Ruby AMQP gem: Using TLS
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,20 +1,24 @@
1
+ # @title Ruby AMQP gem documentation guides
2
+
1
3
  h1. Ruby AMQP gem documentation guides
2
4
 
3
5
  h2. Guide list
4
6
 
5
7
  * {file:docs/GettingStarted.textile Getting started}
6
8
  * {file:docs/ConnectingToTheBroker.textile Connecting to the broker}
7
- * {file:docs/Queues.textile Queues}
8
- * {file:docs/Exchanges.textile Exchanges}
9
+ * {file:docs/Queues.textile Working with queues}
10
+ * {file:docs/Exchanges.textile Working with exchanges}
9
11
  * {file:docs/Bindings.textile Bindings}
10
12
  * {file:docs/Routing.textile Routing}
11
13
  * {file:docs/Durability.textile Durability and message persistence}
12
14
  * {file:docs/ErrorHandling.textile Error handling}
13
15
  * {file:docs/08Migration.textile Upgrading from version 0.6.x/0.7.x to 0.8.x and above}
16
+ * {file:docs/Troubleshooting.textile Troubleshooting and debugging AMQP applications}
14
17
  * {file:docs/Clustering.textile Clustering}
15
18
  * {file:docs/RabbitMQVersions.textile RabbitMQ versions}
16
19
  * {file:docs/ConnectionEncryptionWithTLS.textile Using TLS (SSL)}
17
20
  * {file:docs/VendorSpecificExtensions.textile Vendor-specific extensions to AMQP 0.9.1 spec}
21
+ * {file:docs/RunningTests.textile Running amqp gem test suite}
18
22
 
19
23
 
20
24
  h2. Tell us what you think!
@@ -24,3 +28,21 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
24
28
  key to making documentation better.
25
29
 
26
30
  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
31
+
32
+
33
+ <div id="disqus_thread"></div>
34
+ <script type="text/javascript">
35
+ /* * * CONFIGURATION VARIABLES * * */
36
+ var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
37
+
38
+ var disqus_developer = 0; // set to 1 on local machine for testing comments
39
+ var disqus_identifier = 'amqp_documentation_guides_index';
40
+ var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/DocumentationGuidesIndex.textile';
41
+
42
+ /* * * DON'T EDIT BELOW THIS LINE * * */
43
+ (function() {
44
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
45
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
46
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
47
+ })();
48
+ </script>
@@ -1,3 +1,5 @@
1
+ # @title Ruby AMQP gem: Durability and related matters
2
+
1
3
  h1. Durability and related matters
2
4
 
3
5
 
@@ -9,7 +11,7 @@ topics related to durability, for example, durability in cluster environment.
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
  h2. Entity durability and message persistence
@@ -101,3 +103,22 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
101
103
  key to making documentation better.
102
104
 
103
105
  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
106
+
107
+
108
+
109
+ <div id="disqus_thread"></div>
110
+ <script type="text/javascript">
111
+ /* * * CONFIGURATION VARIABLES * * */
112
+ var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
113
+
114
+ var disqus_developer = 0; // set to 1 on local machine for testing comments
115
+ var disqus_identifier = 'amqp_durability';
116
+ var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/Durability.textile';
117
+
118
+ /* * * DON'T EDIT BELOW THIS LINE * * */
119
+ (function() {
120
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
121
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
122
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
123
+ })();
124
+ </script>
@@ -1,3 +1,5 @@
1
+ # @title Ruby AMQP gem: Error handling and recovery
2
+
1
3
  h1. Error handling and recovery
2
4
 
3
5
  h2. About this guide
@@ -17,7 +19,7 @@ issues like
17
19
 
18
20
  h2. Covered versions
19
21
 
20
- This guide covers amqp gem v0.8.0 and later.
22
+ This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0 and later.
21
23
 
22
24
 
23
25
  h2. Code examples
@@ -233,3 +235,21 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
233
235
  key to making documentation better.
234
236
 
235
237
  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
238
+
239
+
240
+ <div id="disqus_thread"></div>
241
+ <script type="text/javascript">
242
+ /* * * CONFIGURATION VARIABLES * * */
243
+ var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
244
+
245
+ var disqus_developer = 0; // set to 1 on local machine for testing comments
246
+ var disqus_identifier = 'amqp_error_handling';
247
+ var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/ErrorHandling.textile';
248
+
249
+ /* * * DON'T EDIT BELOW THIS LINE * * */
250
+ (function() {
251
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
252
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
253
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
254
+ })();
255
+ </script>
@@ -1,44 +1,193 @@
1
- h1. TBD
1
+ # @title Ruby AMQP gem: Working with exchanges
2
+
3
+ h1. Working with exchanges
2
4
 
3
5
 
4
6
  h2. About this guide
5
7
 
6
- TBD
8
+ This guide covers everything related to exchanges in AMQP 0.9.1, common usage scenarios and how to accomplish typical operations using
9
+ amqp gem.
7
10
 
8
11
 
9
12
  h2. Covered versions
10
13
 
11
- 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.
12
15
 
13
16
 
14
17
  h2. Exchanges in AMQP 0.9.1, briefly
15
18
 
16
- TBD
19
+ h3. What are AMQP exchanges?
20
+
21
+ An exchange accepts messages from a producer application and routes these to message queues. They can be thought of as "mailboxes" of AMQP
22
+ world. Unlike some other messaging middleware products and protocols, in AMQP messages are *not* published directly to queues: they
23
+ are published to exchanges that route them to queue(s) using pre-arranged criteria (called bindings).
24
+
25
+ There are multiple exchange types in AMQP 0.9.1, each with its own routing semantics. Custom exchange types can be created to cover
26
+ sophisticated routing scenarios (for example, routing based on geolocation data), edge cases or just for convenience.
27
+
28
+
29
+ h3. Concept of bindings
30
+
31
+ Binding is an association between a queue and an exchange. Queues must be bound to at least one exchange in order to receive messages from publishers.
32
+ Learn more about bindings in {file:docs/Bindings.textile Bindings guide}.
33
+
34
+
35
+ h3. Attributes
36
+
37
+ Exchanges have several attributes associated with them:
38
+
39
+ * Name
40
+ * Type (direct, fanout, topic, headers or some custom type)
41
+ * Durability
42
+ * Whether exchange is auto-deleted when no longer used
43
+ * Other metadata (aka X-arguments)
17
44
 
18
45
 
19
46
  h2. Exchange types
20
47
 
21
- TBD
48
+ There are 4 built-in exchange types in AMQP 0.9.1:
49
+
50
+ * Direct
51
+ * Fanout
52
+ * Topic
53
+ * Headers
54
+
55
+ As stated previously, each exchange type has own routing semantics and new exchange types can be added by extending brokers with plugins.
56
+ Custom exchange types begin with x-, much like custom HTTP headers, for example, "x-recent-history exchange":https://github.com/videlalvaro/rabbitmq-recent-history-exchange.
57
+
58
+
59
+
60
+
61
+ h2. Message attributes
62
+
63
+ Before we start looking at various exchange types and their routing semantics, we need to introduce idea of message attributes.
64
+ Every AMQP message has a number of *attributes*. Some attributes are important and used very often, other are used rarely. AMQP message attributes are metadata:
65
+ they are similar in purpose to HTTP request and response headers.
66
+
67
+ Every AMQP 0.9.1 message has an attribute called the *routing key*. The routing key is an "address" that the exchange may use to decide how to route
68
+ the message (similar to, but more generic, than URL in HTTP). Most exchange types use routing key to implement routing logic, but some ignore
69
+ it and use other criteria (for example, message content).
70
+
71
+
22
72
 
23
73
 
24
74
  h2. Fanout exchanges
25
75
 
26
- TBD
76
+ Fanout exchanges route messages to all queues bound to it, the routing key is ignored. If N queues are bound to a fanout exchange,
77
+ when a new message is published to that exchange, a *copy of the message* is delivered to all N queues, so fanout exchanges
78
+ are ideal for "broadcast routing":http://en.wikipedia.org/wiki/Broadcasting_%28computing%29 of messages.
79
+
80
+ Graphically this can be represented as
81
+
82
+ !http://upload.wikimedia.org/wikipedia/commons/thumb/d/dc/Broadcast.svg/500px-Broadcast.svg.png!
83
+
84
+ AMQP 0.9.1 brokers must implement fanout exchange type and pre-declare one instance with the name of "amq.fanout".
85
+ This means that applications can rely on that exchange to always be available to them. Each vhost has a separate instance of that exchange,
86
+ it is *not shared across vhosts* for obvious reasons.
87
+
27
88
 
28
89
 
29
90
  h2. Direct exchanges
30
91
 
31
- TBD
92
+ Direct exchange delivers messages to queues based on *message routing key*, an attribute every AMQP 0.9.1 message has.
93
+
94
+ Here is how it works:
95
+
96
+ * A queue binds to the exchange with a routing key, K.
97
+ * When a new message with routing key R arrives to direct exchange, the exchange routes it to the queue if K = R.
98
+
99
+ Direct exchange is ideal for "unicast routing":http://en.wikipedia.org/wiki/Unicast of messages (although it can be used for "multicast routing":http://en.wikipedia.org/wiki/Multicast, too).
100
+
101
+ !http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Unicast.svg/500px-Unicast.svg.png!
102
+
103
+ AMQP 0.9.1 brokers must implement direct exchange type and pre-declare two instances
104
+
105
+ * *amq.direct*.
106
+ * *""* (unnamed, referred to as an empty string by many clients including amqp Ruby gem) exchange known as *default exchange*.
107
+
108
+ This means that applications can rely on those exchanges to always be available to them. Each vhost has separate instances of those exchanges,
109
+ they are *not shared across vhosts* for obvious reasons.
110
+
111
+
112
+ h3. Default exchange
113
+
114
+ Default exchange is a direct exchange with no name (amqp gem refers to it using an empty string) pre-declared by the broker. It has one key special
115
+ property that makes it very useful for simple applications: *every queue is automatically bound to it with a routing key the same as queue name".
116
+
117
+ For example, when you declare a queue with the name of "search.indexing.online", AMQP broker will bind it to the default exchange using
118
+ "search.indexing.online" as routing key. So a message publishes to the default exchange with routing key = "search.indexing.online"
119
+ will be routed to the queue "search.indexing.online". In other words, default exchange makes it possible to "deliver messages directly to queues",
120
+ even though that is not technically correct.
121
+
122
+
123
+ amqp gem offers two ways of obtaining of the default exchange: {AMQP::Channel#default_exchange} and {AMQP::Channel#direct} (use empty string as exchange name).
124
+ {AMQP::Exchange#initialize} can be used as well but requires more effort and for this particular case offers no benefits over instance methods on {AMQP::Channel}.
125
+
126
+ The default exchange is what the "Hello, World" example uses:
127
+
128
+ {include:file:examples/hello_world.rb}
129
+
32
130
 
33
131
 
34
132
  h2. Topic exchanges
35
133
 
134
+ Topic exchanges route messages to one or many queues based on matching between message routing key and pattern that was used for binding
135
+ queue to the exchange.
136
+
137
+
138
+ Topic exchanges are commonly used for "multicast routing":http://en.wikipedia.org/wiki/Multicast of messages.
139
+
140
+ !http://upload.wikimedia.org/wikipedia/commons/thumb/3/30/Multicast.svg/500px-Multicast.svg.png!
141
+
142
+ Topic exchanges can be used for "broadcast routing":http://en.wikipedia.org/wiki/Broadcasting_%28computing%29 but usually fanout exchanges are more efficient at that.
143
+
144
+
145
+
146
+ Here is an example of topic exchange in action:
147
+
148
+ {include:file:examples/routing/weather_updates.rb}
149
+
150
+ TBD
151
+
152
+
153
+
154
+ h2. Headers exchanges
155
+
156
+
157
+
158
+ TBD
159
+
160
+
161
+
162
+ h2. Custom exchange types
163
+
164
+ TBD
165
+
166
+
167
+
168
+ h2. Declaring/Instantiating exchanges
169
+
170
+
171
+
172
+ Below is an example of {AMQP::Exchange#initialize} used with a callback:
173
+
174
+ {include:file:examples/exchanges/declare_an_exchange_without_assignment.rb}
175
+
176
+
36
177
  TBD
37
178
 
38
179
 
39
180
 
40
181
  h2. Publishing messages
41
182
 
183
+
184
+ h3. Publishing one-off messages
185
+
186
+ The following example publishes a message and *safely* closes AMQP connection after that by passing a block
187
+ to {AMQP::Exchange#publish}:
188
+
189
+ {include:file:examples/publishing/publishing_a_one_off_message.rb}
190
+
42
191
  TBD
43
192
 
44
193
 
@@ -56,13 +205,18 @@ TBD
56
205
 
57
206
  h2. Deleting exchanges
58
207
 
208
+
209
+ Exchanges are be *auto-deleted*. An example that uses two auto-deleted exchanges:
210
+
211
+ {include:file:examples/exchanges/autodeletion_of_exchanges.rb}
212
+
59
213
  TBD
60
214
 
61
215
 
62
216
 
63
217
  h2. Exchange durability vs Message durability
64
218
 
65
- TBD
219
+ See {file:docs/Durability.textile Durability guide}
66
220
 
67
221
 
68
222
 
@@ -74,7 +228,7 @@ TBD
74
228
 
75
229
  h2. Vendor-specific extensions related to exchanges
76
230
 
77
- TBD
231
+ See {file:docs/VendorSpecificExtensions.textile Vendor-specific Extensions guide}
78
232
 
79
233
 
80
234
 
@@ -90,3 +244,21 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
90
244
  key to making documentation better.
91
245
 
92
246
  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
247
+
248
+
249
+ <div id="disqus_thread"></div>
250
+ <script type="text/javascript">
251
+ /* * * CONFIGURATION VARIABLES * * */
252
+ var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
253
+
254
+ var disqus_developer = 0; // set to 1 on local machine for testing comments
255
+ var disqus_identifier = 'amqp_exchanges';
256
+ var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/Exchanges.textile';
257
+
258
+ /* * * DON'T EDIT BELOW THIS LINE * * */
259
+ (function() {
260
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
261
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
262
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
263
+ })();
264
+ </script>
@@ -1,3 +1,5 @@
1
+ # @title Ruby AMQP gem: Getting Started with AMQP and Ruby
2
+
1
3
  h1. Getting started with AMQP Ruby gem
2
4
 
3
5
 
@@ -8,38 +10,46 @@ It should take about 20 minutes to read and study provided code examples. This g
8
10
 
9
11
  * Installing RabbitMQ, a mature popular implementation of multiple versions of AMQP protocol.
10
12
  * Installing amqp gem via "Rubygems":http://rubygems.org and "Bundler":http://gembundler.com.
11
- * Running a "Hello, world"-like code example, a simple demonstration of 1:1 communication.
13
+ * Running the "Hello, world" of messaging, a simple demonstration of 1:1 communication.
12
14
  * Creating a "Twitter like" publish/subscribe example with 1 publisher and 4 subscribers, a case of 1:n communication.
13
15
  * Creating a topic routing example with 2 publishers and 8 subscribers, a case of n:m communication when subscribers only receive messages they are interested in.
14
16
 
15
17
 
16
18
  h2. Covered versions
17
19
 
18
- This guide covers amqp gem v0.8.0 and later.
20
+ This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0 and later.
19
21
 
20
22
 
21
23
  h2. Installing RabbitMQ
22
24
 
23
- RabbitMQ site has a good "installation guide":http://www.rabbitmq.com/install.html that covers many operating systems.
24
- On Mac OS X, the fastest way to install RabbitMQ is with Homebrew:
25
+ "RabbitMQ site":http://rabbitmq.com has a good "installation guide":http://www.rabbitmq.com/install.html that covers many operating systems.
26
+ On Mac OS X, the fastest way to install RabbitMQ is with "Homebrew":http://mxcl.github.com/homebrew/:
25
27
 
28
+ <pre>
26
29
  <code>
27
30
  brew install rabbitmq
28
31
  </code>
32
+ </pre>
29
33
 
30
34
  then run it:
35
+
36
+ <pre>
31
37
  <code>
32
38
  rabbitmq-server
33
39
  </code>
40
+ </pre>
41
+
42
+ On Debian and Ubuntu, you can either "download RabbitMQ .deb package":http://www.rabbitmq.com/server.html and install it with
43
+ "dpkg":http://www.debian.org/doc/FAQ/ch-pkgtools.en.html or use "apt repository RabbitMQ team provides":http://www.rabbitmq.com/debian.html#apt.
44
+ For RPM-based distributions like RedHat or CentOS RabbitMQ team provides an "RPM package":http://www.rabbitmq.com/install.html#rpm.
34
45
 
35
- On "Debian and Ubuntu":http://www.rabbitmq.com/install.html#debian, you can either download a .deb package and install it with
36
- dpkg or use apt repository RabbitMQ team provides. RabbitMQ package in even recent (10.10) versions of Ubuntu are old and won't
37
- work with amqp gem 0.8.0 and later (we need at least version 2.0). For "RPM-based distributions":http://www.rabbitmq.com/install.html#rpm like RedHat
38
- or CentOS RabbitMQ team provides an RPM package.
46
+ <span class="note">
47
+ RabbitMQ package in even recent (10.10) versions of Ubuntu are outdated and *won't work with amqp gem 0.8.0 and later* (we need at least version 2.0).
48
+ </span>
39
49
 
40
50
 
41
51
 
42
- h2. Installing amqp gem
52
+ h2. Installing Ruby amqp gem
43
53
 
44
54
  h3. Make sure you have Ruby installed
45
55
 
@@ -55,17 +65,27 @@ This guides assumes you have one of the supported Ruby implementations installed
55
65
  h3. With Rubygems
56
66
 
57
67
  To get amqp gem 0.8.0
68
+
69
+ h4. On Microsoft Windows 7
70
+
58
71
  <pre>
59
- <code>
60
- gem install amqp --pre
61
- </code>
72
+ gem install eventmachine --pre
73
+ gem install amqp --pre --version "~> 0.8.0.RC12"
74
+ </pre>
75
+
76
+ h4. On other OSes or JRuby:
77
+
78
+ <pre>
79
+ gem install amqp --pre --version "~> 0.8.0.RC12"
62
80
  </pre>
63
81
 
64
82
  h3. With Bundler
65
83
 
66
84
  <pre>
67
85
  <code>
68
- gem "amqp", :git => "git://github.com/ruby-amqp/amqp.git", :branch => "master"
86
+ source :rubygems
87
+
88
+ gem "amqp", "~> 0.8.0.RC12" # optionally: :git => "git://github.com/ruby-amqp/amqp.git", :branch => "master"
69
89
  </code>
70
90
  </pre>
71
91
 
@@ -80,43 +100,18 @@ irb -rubygems
80
100
  :001 > require "amqp"
81
101
  => true
82
102
  :002 > AMQP::VERSION
83
- => "0.8.0.rc2"
103
+ => "0.8.0.rc12"
84
104
  </code>
85
105
  </pre>
86
106
 
87
107
 
88
- h2. A "Hello, world" example
89
-
90
- Lets begin with a classic Hello, world example. First, here's the code:
91
-
92
- <pre>
93
- <code>
94
- #!/usr/bin/env ruby
95
- # encoding: utf-8
96
-
97
- require "rubygems"
98
- require "amqp"
99
-
100
- EventMachine.run do
101
- connection = AMQP.connect(:host => '127.0.0.1')
102
- puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
108
+ h2. "Hello, world" example
103
109
 
104
- channel = AMQP::Channel.new(connection)
105
- queue = channel.queue("amqpgem.examples.hello_world", :auto_delete => true)
106
- exchange = channel.direct("")
110
+ Lets begin with the classic "Hello, world" example. First, here's the code:
107
111
 
108
- queue.subscribe do |payload|
109
- puts "Received a message: #{payload}. Disconnecting..."
112
+ <script src="https://gist.github.com/998690.js"> </script>
110
113
 
111
- connection.close {
112
- EM.stop { exit }
113
- }
114
- end
115
-
116
- exchange.publish "Hello, world!", :routing_key => queue.name
117
- end
118
- </code>
119
- </pre>
114
+ (if the example above isn't displayed, see this "gist":https://gist.github.com/998690)
120
115
 
121
116
  This example demonstrates a very common communication scenario: app A wants to publish a message that will end up in
122
117
  a queue that app B listens on. In this example, queue name is "amqpgem.examples.hello". Lets go through this example
@@ -214,86 +209,28 @@ as message's routing key. This is how our message ends up in amqpgem.examples.he
214
209
 
215
210
  This first example can be modified to use method chaining technique:
216
211
 
217
- <pre>
218
- <code>
219
- #!/usr/bin/env ruby
220
- # encoding: utf-8
221
-
222
- require "rubygems"
223
- require "amqp"
224
-
225
- EventMachine.run do
226
- AMQP.connect(:host => '127.0.0.1') do |connection|
227
- puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
228
-
229
- channel = AMQP::Channel.new(connection)
212
+ <script src="https://gist.github.com/998691.js"> </script>
230
213
 
231
- channel.queue("amqpgem.examples.helloworld", :auto_delete => true).subscribe do |payload|
232
- puts "Received a message: #{payload}. Disconnecting..."
233
-
234
- connection.close {
235
- EM.stop { exit }
236
- }
237
- end
238
-
239
- channel.direct("").publish "Hello, world!", :routing_key => "amqpgem.examples.helloworld"
240
- end
241
- end
242
- </code>
243
- </pre>
214
+ (if the example above isn't displayed, see this "gist":https://gist.github.com/998691)
244
215
 
245
216
  With classes and methods introduced in this example, lets move on to a little bit more
246
217
  sophisticated one.
247
218
 
248
219
 
249
- h2. Babblr: one-to-many publish/subscribe example
220
+ h2. Blabblr: one-to-many publish/subscribe example
250
221
 
251
222
  Previous example demonstrated how connection to the broker is made and how to do 1:1 communication
252
223
  using default exchange. Now lets take a look at another common scenario: broadcast, or multiple consumers
253
224
  and one producer.
254
225
 
255
226
  A very well know example of broadcast is Twitter: every time a person tweets, followers receive a notification.
256
- Blabbr, our imaginary information network, models this scenario this way: every network member has a separate
227
+ Blabbr, our imaginary information network, models this scenario: every network member has a separate
257
228
  queue and publishes blabs to a separate exchange. 3 Blabbr members, Joe, Aaron and Bob, follow official NBA
258
229
  account on Blabbr to get updates about what is up in the world of basketball. Here is the code:
259
230
 
260
- <pre>
261
- <code>
262
- #!/usr/bin/env ruby
263
- # encoding: utf-8
264
-
265
- require "rubygems"
266
- require "amqp"
267
-
268
- AMQP.start("amqp://dev.rabbitmq.com:5672") do |connection|
269
- channel = AMQP::Channel.new(connection)
270
- exchange = channel.fanout("nba.scores")
271
-
272
- channel.queue("joe", :auto_delete => true).bind(exchange).subscribe do |payload|
273
- puts "#{payload} => joe"
274
- end
275
-
276
- channel.queue("aaron", :auto_delete => true).bind(exchange).subscribe do |payload|
277
- puts "#{payload} => aaron"
278
- end
279
-
280
- channel.queue("bob", :auto_delete => true).bind(exchange).subscribe do |payload|
281
- puts "#{payload} => bob"
282
- end
283
-
284
- exchange.publish("BOS 101, NYK 89").publish("ORL 85, ALT 88")
231
+ <script src="https://gist.github.com/998692.js"> </script>
285
232
 
286
- # disconnect & exit after 1 second
287
- EventMachine.add_timer(1) do
288
- exchange.delete
289
-
290
- connection.close {
291
- EM.stop { exit }
292
- }
293
- end
294
- end
295
- </code>
296
- </pre>
233
+ (if the example above isn't displayed, see this "gist":https://gist.github.com/998692)
297
234
 
298
235
  First line has a few difference from "Hello, world" example above:
299
236
 
@@ -398,66 +335,9 @@ on North America updates list.
398
335
 
399
336
  Here is the code:
400
337
 
401
- <pre>
402
- <code>
403
- #!/usr/bin/env ruby
404
- # encoding: utf-8
338
+ <script src="https://gist.github.com/998694.js"> </script>
405
339
 
406
- require "rubygems"
407
- require "amqp"
408
-
409
- EventMachine.run do
410
- AMQP.connect do |connection|
411
- channel = AMQP::Channel.new(connection)
412
- exchange = channel.topic("pub/sub", :auto_delete => true)
413
-
414
- # Subscribers.
415
- channel.queue("", :exclusive => true) do |queue|
416
- queue.bind(exchange, :routing_key => "americas.north.#").subscribe do |headers, payload|
417
- puts "An update for North America: #{payload}, routing key is #{headers.routing_key}"
418
- end
419
- end
420
- channel.queue("americas.south").bind(exchange, :routing_key => "americas.south.#").subscribe do |headers, payload|
421
- puts "An update for South America: #{payload}, routing key is #{headers.routing_key}"
422
- end
423
- channel.queue("us.california").bind(exchange, :routing_key => "americas.north.us.ca.*").subscribe do |headers, payload|
424
- puts "An update for US/California: #{payload}, routing key is #{headers.routing_key}"
425
- end
426
- channel.queue("us.tx.austin").bind(exchange, :routing_key => "#.tx.austin").subscribe do |headers, payload|
427
- puts "An update for Austin, TX: #{payload}, routing key is #{headers.routing_key}"
428
- end
429
- channel.queue("it.rome").bind(exchange, :routing_key => "europe.italy.rome").subscribe do |headers, payload|
430
- puts "An update for Rome, Italy: #{payload}, routing key is #{headers.routing_key}"
431
- end
432
- channel.queue("asia.hk").bind(exchange, :routing_key => "asia.southeast.hk.#").subscribe do |headers, payload|
433
- puts "An update for Hong Kong: #{payload}, routing key is #{headers.routing_key}"
434
- end
435
-
436
- EM.add_timer(1) do
437
- exchange.publish("San Diego update", :routing_key => "americas.north.us.ca.sandiego").
438
- publish("Berkeley update", :routing_key => "americas.north.us.ca.berkeley").
439
- publish("San Francisco update", :routing_key => "americas.north.us.ca.sanfrancisco").
440
- publish("New York update", :routing_key => "americas.north.us.ny.newyork").
441
- publish("São Paolo update", :routing_key => "americas.south.brazil.saopaolo").
442
- publish("Hong Kong update", :routing_key => "asia.southeast.hk.hongkong").
443
- publish("Kyoto update", :routing_key => "asia.southeast.japan.kyoto").
444
- publish("Shanghai update", :routing_key => "asia.southeast.prc.shanghai").
445
- publish("Rome update", :routing_key => "europe.italy.roma").
446
- publish("Paris update", :routing_key => "europe.france.paris")
447
- end
448
-
449
-
450
- show_stopper = Proc.new {
451
- connection.close do
452
- EM.stop
453
- end
454
- }
455
-
456
- EM.add_timer(2, show_stopper)
457
- end
458
- end
459
- </code>
460
- </pre>
340
+ (if the example above isn't displayed, see this "gist":https://gist.github.com/998694)
461
341
 
462
342
  First line that is different from Blabbr example is
463
343
 
@@ -568,7 +448,7 @@ This tutorial ends here. Congratulations! You have learned quite a bit about bot
568
448
 
569
449
  h2. What to read next
570
450
 
571
- Documentation is organized as a {file:docs/DocumentationGuidesIndex.textile Number of guides}, covering all kinds of
451
+ Documentation is organized as a number of {file:docs/DocumentationGuidesIndex.textile documentation guides}, covering all kinds of
572
452
  topics from {file:docs/Routing.textile routing} to {file:docs/ErrorHandling.textile error handling} to
573
453
  {file:docs/VendorSpecificExchanges.textile Broker-specific AMQP 0.9.1 extensions}.
574
454
 
@@ -590,3 +470,21 @@ what was unclear? what wasn't covered? maybe you don't like guide style or gramm
590
470
  key to making documentation better.
591
471
 
592
472
  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
473
+
474
+
475
+ <div id="disqus_thread"></div>
476
+ <script type="text/javascript">
477
+ /* * * CONFIGURATION VARIABLES * * */
478
+ var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname
479
+
480
+ var disqus_developer = 0; // set to 1 on local machine for testing comments
481
+ var disqus_identifier = 'amqp_connecting_to_the_broker';
482
+ var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/GettingStarted.textile';
483
+
484
+ /* * * DON'T EDIT BELOW THIS LINE * * */
485
+ (function() {
486
+ var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
487
+ dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
488
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
489
+ })();
490
+ </script>