amqp 0.9.10 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -3
- data/CHANGELOG +4 -0
- data/Gemfile +1 -0
- data/README.md +72 -81
- data/amqp.gemspec +14 -5
- data/docs/08Migration.textile +0 -4
- data/docs/AMQP091ModelExplained.textile +0 -5
- data/docs/Bindings.textile +0 -4
- data/docs/Clustering.textile +0 -4
- data/docs/ConnectingToTheBroker.textile +1 -5
- data/docs/ConnectionEncryptionWithTLS.textile +0 -4
- data/docs/DocumentationGuidesIndex.textile +0 -4
- data/docs/Durability.textile +0 -4
- data/docs/ErrorHandling.textile +40 -106
- data/docs/Exchanges.textile +0 -4
- data/docs/GettingStarted.textile +6 -10
- data/docs/PatternsAndUseCases.textile +1 -4
- data/docs/Queues.textile +0 -4
- data/docs/RabbitMQVersions.textile +0 -4
- data/docs/RunningTests.textile +0 -4
- data/docs/TestingWithEventedSpec.textile +0 -4
- data/docs/Troubleshooting.textile +0 -4
- data/docs/VendorSpecificExtensions.textile +0 -4
- data/examples/error_handling/hello_world_producer.rb +1 -1
- data/examples/issues/issue_121.rb +23 -0
- data/examples/patterns/request_reply/client.rb +2 -1
- data/examples/patterns/request_reply/server.rb +1 -0
- data/examples/publishing/returned_messages.rb +1 -1
- data/lib/amqp.rb +0 -7
- data/lib/amqp/channel.rb +15 -33
- data/lib/amqp/client.rb +2 -2
- data/lib/amqp/compatibility/ruby187_patchlevel_check.rb +4 -4
- data/lib/amqp/connection.rb +0 -1
- data/lib/amqp/consumer.rb +2 -2
- data/lib/amqp/exceptions.rb +1 -10
- data/lib/amqp/exchange.rb +5 -5
- data/lib/amqp/queue.rb +23 -47
- data/lib/amqp/session.rb +4 -4
- data/lib/amqp/version.rb +1 -1
- data/spec/integration/basic_get_spec.rb +24 -80
- data/spec/integration/basic_return_spec.rb +3 -3
- data/spec/integration/channel_level_exception_with_multiple_channels_spec.rb +1 -0
- data/spec/integration/exchange_declaration_spec.rb +102 -71
- data/spec/integration/extensions/rabbitmq/publisher_confirmations_spec.rb +17 -1
- data/spec/integration/fanout_exchange_routing_spec.rb +1 -1
- data/spec/integration/immediate_messages_spec.rb +59 -0
- data/spec/integration/multiple_consumers_per_queue_spec.rb +101 -39
- data/spec/integration/queue_redeclaration_with_incompatible_attributes_spec.rb +12 -25
- data/spec/integration/regressions/concurrent_publishing_on_the_same_channel_spec.rb +1 -1
- data/spec/integration/reply_queue_communication_spec.rb +2 -1
- data/spec/integration/store_and_forward_spec.rb +9 -6
- data/spec/integration/topic_subscription_spec.rb +4 -5
- data/spec/spec_helper.rb +2 -8
- data/spec/unit/amqp/connection_spec.rb +1 -3
- metadata +112 -116
- data/examples/deprecated/default_thread_local_channel_instance.rb +0 -34
- data/examples/legacy/ack.rb +0 -70
- data/examples/legacy/callbacks.rb +0 -45
- data/examples/legacy/clock.rb +0 -74
- data/examples/legacy/hashtable.rb +0 -60
- data/examples/legacy/logger.rb +0 -92
- data/examples/legacy/multiclock.rb +0 -56
- data/examples/legacy/pingpong.rb +0 -51
- data/examples/legacy/primes-simple.rb +0 -29
- data/examples/legacy/primes.rb +0 -74
- data/examples/legacy/stocks.rb +0 -59
- data/lib/amqp/deprecated/fork.rb +0 -17
- data/lib/amqp/deprecated/logger.rb +0 -100
- data/lib/amqp/deprecated/mq.rb +0 -22
- data/lib/amqp/deprecated/rpc.rb +0 -169
- data/lib/amqp/ext/em.rb +0 -3
- data/lib/amqp/ext/emfork.rb +0 -72
- data/lib/amqp/logger.rb +0 -19
- data/lib/amqp/rpc.rb +0 -20
- data/lib/mq.rb +0 -35
- data/lib/mq/logger.rb +0 -4
- data/lib/mq/rpc.rb +0 -4
- data/spec/integration/remove_individual_binding_spec.rb +0 -51
data/docs/Durability.textile
CHANGED
data/docs/ErrorHandling.textile
CHANGED
@@ -2,16 +2,9 @@
|
|
2
2
|
|
3
3
|
h1. Error handling and recovery
|
4
4
|
|
5
|
-
h2. This Documentation Has Moved to rubyamqp.info
|
6
|
-
|
7
|
-
amqp gem documentation guides are now hosted on "rubyamqp.info":http://rubyamqp.info.
|
8
|
-
|
9
5
|
h2. About this guide
|
10
6
|
|
11
|
-
Development of a robust application, be it message publisher or message consumer, involves dealing with
|
12
|
-
multiple kinds of failures: protocol exceptions, network failures, broker failures and so on.
|
13
|
-
Correct error handling and recovery is not easy. This guide explains how amqp gem helps you in dealing with
|
14
|
-
issues like
|
7
|
+
Development of a robust application, be it message publisher or message consumer, involves dealing with multiple kinds of failures: protocol exceptions, network failures, broker failures and so on. Correct error handling and recovery is not easy. This guide explains how amqp gem helps you in dealing with issues like
|
15
8
|
|
16
9
|
* Initial broker connection failures
|
17
10
|
* Network connection interruption
|
@@ -35,15 +28,11 @@ This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0.RC14 a
|
|
35
28
|
|
36
29
|
h2. Code examples
|
37
30
|
|
38
|
-
There are several {https://github.com/ruby-amqp/amqp/tree/master/examples/error_handling examples} in the git repository dedicated to the topic of error handling and recovery. Feel
|
39
|
-
free to contribute new examples.
|
40
|
-
|
31
|
+
There are several {https://github.com/ruby-amqp/amqp/tree/master/examples/error_handling examples} in the git repository dedicated to the topic of error handling and recovery. Feel free to contribute new examples.
|
41
32
|
|
42
33
|
h3. Initial broker connection failures
|
43
34
|
|
44
|
-
When applications connect to the broker, they need to handle connection failures. Networks are not 100% reliable, even with modern system configuration tools
|
45
|
-
like Chef or Puppet misconfigurations happen and broker might be down, too. Error detection should happen as early as possible. There are two ways of detecting
|
46
|
-
TCP connection failure, the first one is to catch an exception:
|
35
|
+
When applications connect to the broker, they need to handle connection failures. Networks are not 100% reliable, even with modern system configuration tools like Chef or Puppet misconfigurations happen and broker might be down, too. Error detection should happen as early as possible. There are two ways of detecting TCP connection failure, the first one is to catch an exception:
|
47
36
|
|
48
37
|
<pre>
|
49
38
|
<code>
|
@@ -60,9 +49,7 @@ end
|
|
60
49
|
Full example:
|
61
50
|
<script src="https://gist.github.com/1016238.js"> </script>
|
62
51
|
|
63
|
-
{AMQP.connect} (and {AMQP.start}) will raise {AMQP::TCPConnectionFailed} if connection fails. Code that catches it can write to log
|
64
|
-
about the issue or use retry to execute begin block one more time. Because initial connection failures are due to misconfiguration or network outage, reconnection
|
65
|
-
to the same endpoint (hostname, port, vhost combination) will result in the same issue over and over. TBD: failover, connection to the cluster.
|
52
|
+
{AMQP.connect} (and {AMQP.start}) will raise {AMQP::TCPConnectionFailed} if connection fails. Code that catches it can write to log about the issue or use retry to execute begin block one more time. Because initial connection failures are due to misconfiguration or network outage, reconnection to the same endpoint (hostname, port, vhost combination) will result in the same issue over and over. TBD: failover, connection to the cluster.
|
66
53
|
|
67
54
|
Alternative way of handling connection failure is with an errback (a callback for specific kind of error):
|
68
55
|
|
@@ -85,16 +72,14 @@ Full example:
|
|
85
72
|
|
86
73
|
:on_tcp_connection_failure option accepts any object that responds to #call.
|
87
74
|
|
88
|
-
If you connect to the broker from a code in a class (as opposed to top-level scope in a script), Object#method can be used to pass object method as a handler
|
89
|
-
instead of a Proc.
|
75
|
+
If you connect to the broker from a code in a class (as opposed to top-level scope in a script), Object#method can be used to pass object method as a handler instead of a Proc.
|
90
76
|
|
91
77
|
TBD: provide an example
|
92
78
|
|
93
79
|
|
94
80
|
h3. Authentication failures
|
95
81
|
|
96
|
-
Another reason why connection may fail is authentication failure. Handling authentication failure is very similar to handling initial TCP
|
97
|
-
connection failure:
|
82
|
+
Another reason why connection may fail is authentication failure. Handling authentication failure is very similar to handling initial TCP connection failure:
|
98
83
|
|
99
84
|
<script src="https://gist.github.com/1016233.js"> </script>
|
100
85
|
|
@@ -105,19 +90,13 @@ default handler raises {AMQP::PossibleAuthenticationFailureError}:
|
|
105
90
|
|
106
91
|
<script src="https://gist.github.com/1016234.js"> </script>
|
107
92
|
|
108
|
-
In case you wonder why callback name has "possible" in it: {http://bit.ly/
|
109
|
-
simply close TCP connection without sending any more data when an exception (such as authentication failure) occurs before AMQP connection
|
110
|
-
is open. In practice, however, when broker closes TCP connection between successful TCP connection and before AMQP connection is open,
|
111
|
-
it means that authentication has failed.
|
93
|
+
In case you wonder why callback name has "possible" in it: {http://bit.ly/amqp091spec AMQP 0.9.1 spec} requires broker implementations to simply close TCP connection without sending any more data when an exception (such as authentication failure) occurs before AMQP connection is open. In practice, however, when broker closes TCP connection between successful TCP connection and before AMQP connection is open, it means that authentication has failed.
|
112
94
|
|
113
95
|
|
114
96
|
|
115
97
|
h2. Handling network connection interruptions
|
116
98
|
|
117
|
-
Network connectivity issues are sad fact of life in modern software systems. Event small products and projects these days consist of multiple
|
118
|
-
applications, often running on more than one machine. Ruby amqp gem detects TCP connection failures and lets you handle them by
|
119
|
-
defining a callback using {AMQP::Session#on_tcp_connection_loss}. That callback will be run when TCP connection fails, and will be passed
|
120
|
-
two parameters: connection object and settings of the last successful connection.
|
99
|
+
Network connectivity issues are sad fact of life in modern software systems. Event small products and projects these days consist of multiple applications, often running on more than one machine. Ruby amqp gem detects TCP connection failures and lets you handle them by defining a callback using {AMQP::Session#on_tcp_connection_loss}. That callback will be run when TCP connection fails, and will be passed two parameters: connection object and settings of the last successful connection.
|
121
100
|
|
122
101
|
<pre>
|
123
102
|
<code>
|
@@ -128,35 +107,25 @@ end
|
|
128
107
|
</code>
|
129
108
|
</pre>
|
130
109
|
|
131
|
-
Sometimes it is necessary for other entities in an application to react to network failures. amqp gem 0.8.0 and later provides a number event
|
132
|
-
handlers to make this task easier for developers. This set of features is know as the "shutdown protocol" (the word "protocol" here means
|
133
|
-
"API interface" or "behavior", not network protocol).
|
110
|
+
Sometimes it is necessary for other entities in an application to react to network failures. amqp gem 0.8.0 and later provides a number event handlers to make this task easier for developers. This set of features is know as the "shutdown protocol" (the word "protocol" here means "API interface" or "behavior", not network protocol).
|
134
111
|
|
135
|
-
{AMQP::Session}, {AMQP::Channel}, {AMQP::Exchange}, {AMQP::Queue} and {AMQP::Consumer all implement shutdown protocol and thus error
|
136
|
-
handling API is consistent for all classes, with {AMQP::Session} and #{AMQP::Channel} having a few methods other entities do not have.
|
112
|
+
{AMQP::Session}, {AMQP::Channel}, {AMQP::Exchange}, {AMQP::Queue} and {AMQP::Consumer all implement shutdown protocol and thus error handling API is consistent for all classes, with {AMQP::Session} and #{AMQP::Channel} having a few methods other entities do not have.
|
137
113
|
|
138
114
|
The Shutdown protocol revolves around two events:
|
139
115
|
|
140
116
|
* Network connection fails
|
141
117
|
* Broker closes AMQP connection (or channel)
|
142
118
|
|
143
|
-
In this section, we concentrate only on the former. When network connection fails, the underlying networking library detects it and
|
144
|
-
runs a piece of code on {AMQP::Session} to handle it. That, in turn, propagates this event to channels, channels propagate it to
|
145
|
-
exchanges and queues, queues propagate it to their consumers (if any). Each of these entities in the object graph can react
|
146
|
-
to network interruption by executing application-defined callbacks.
|
119
|
+
In this section, we concentrate only on the former. When network connection fails, the underlying networking library detects it and runs a piece of code on {AMQP::Session} to handle it. That, in turn, propagates this event to channels, channels propagate it to exchanges and queues, queues propagate it to their consumers (if any). Each of these entities in the object graph can react to network interruption by executing application-defined callbacks.
|
147
120
|
|
148
121
|
h3. Shutdown Protocol methods on AMQP::Session
|
149
122
|
|
150
123
|
* {AMQP::Session#on_tcp_connection_loss}
|
151
124
|
* {AMQP::Session#on_connection_interruption}
|
152
125
|
|
153
|
-
The difference between these methods is that {AMQP::Session#on_tcp_connection_loss} is used to define a callback that will
|
154
|
-
be executed *once* when TCP connection fails. It is possible that reconnection attempts will not succeed immediately, so
|
155
|
-
there will be subsequent failures. To react to those, {AMQP::Session#on_connection_interruption} method is used.
|
126
|
+
The difference between these methods is that {AMQP::Session#on_tcp_connection_loss} is used to define a callback that will be executed *once* when TCP connection fails. It is possible that reconnection attempts will not succeed immediately, so there will be subsequent failures. To react to those, {AMQP::Session#on_connection_interruption} method is used.
|
156
127
|
|
157
|
-
First argument that both of these methods yield to the handler your application defines is the connection itself. This is
|
158
|
-
done to make sure you can register Ruby objects as handlers, and they do not have to keep any state around (for example,
|
159
|
-
connection instances):
|
128
|
+
First argument that both of these methods yield to the handler your application defines is the connection itself. This is done to make sure you can register Ruby objects as handlers, and they do not have to keep any state around (for example, connection instances):
|
160
129
|
|
161
130
|
<pre>
|
162
131
|
<code>
|
@@ -185,17 +154,14 @@ connection.on_connection_interruption(&handler.method(:handle))
|
|
185
154
|
|
186
155
|
Note that {AMQP::Session#on_connection_interruption} callback is called *before* this event is propagated to channels, queues and so on.
|
187
156
|
|
188
|
-
Different applications handle connection failures differently. It is very common to use {AMQP::Session#reconnect} method
|
189
|
-
to schedule a reconnection to the same host, or use {AMQP::Session#reconnect_to} to connect to a different one.
|
157
|
+
Different applications handle connection failures differently. It is very common to use {AMQP::Session#reconnect} method to schedule a reconnection to the same host, or use {AMQP::Session#reconnect_to} to connect to a different one.
|
190
158
|
|
191
|
-
For some applications it is OK to simply exit and wait to be restarted at a later point in time, for example, by a process
|
192
|
-
monitoring system like Nagios or Monit.
|
159
|
+
For some applications it is OK to simply exit and wait to be restarted at a later point in time, for example, by a process monitoring system like Nagios or Monit.
|
193
160
|
|
194
161
|
|
195
162
|
h3. Shutdown Protocol methods on AMQP::Channel
|
196
163
|
|
197
|
-
{AMQP::Channel} provides only one method: {AMQP::Channel#on_connection_interruption}, that registers a callback similar to
|
198
|
-
the one seen in the previous section:
|
164
|
+
{AMQP::Channel} provides only one method: {AMQP::Channel#on_connection_interruption}, that registers a callback similar to the one seen in the previous section:
|
199
165
|
|
200
166
|
<pre>
|
201
167
|
<code>
|
@@ -205,8 +171,7 @@ end
|
|
205
171
|
</code>
|
206
172
|
</pre>
|
207
173
|
|
208
|
-
Note that {AMQP::Channel#on_connection_interruption} callback is called *after* this event is propagated to exchanges, queues and so on.
|
209
|
-
Right after that channel state is reset, except for error handling/recovery-related callbacks.
|
174
|
+
Note that {AMQP::Channel#on_connection_interruption} callback is called *after* this event is propagated to exchanges, queues and so on. Right after that channel state is reset, except for error handling/recovery-related callbacks.
|
210
175
|
|
211
176
|
<span class="note">
|
212
177
|
Many applications do not need per-channel network failure handling.
|
@@ -233,8 +198,7 @@ Many applications do not need per-exchange network failure handling.
|
|
233
198
|
|
234
199
|
h3. Shutdown Protocol methods on AMQP::Queue
|
235
200
|
|
236
|
-
{AMQP::Queue} provides only one method: {AMQP::Queue#on_connection_interruption}, that registers a callback similar to
|
237
|
-
the one seen in the previous section:
|
201
|
+
{AMQP::Queue} provides only one method: {AMQP::Queue#on_connection_interruption}, that registers a callback similar to the one seen in the previous section:
|
238
202
|
|
239
203
|
<pre>
|
240
204
|
<code>
|
@@ -253,8 +217,7 @@ Many applications do not need per-queue network failure handling.
|
|
253
217
|
|
254
218
|
h3. Shutdown Protocol methods on AMQP::Consumer
|
255
219
|
|
256
|
-
{AMQP::Consumer} provides only one method: {AMQP::Consumer#on_connection_interruption}, that registers a callback similar to
|
257
|
-
the one seen in the previous section:
|
220
|
+
{AMQP::Consumer} provides only one method: {AMQP::Consumer#on_connection_interruption}, that registers a callback similar to the one seen in the previous section:
|
258
221
|
|
259
222
|
<pre>
|
260
223
|
<code>
|
@@ -283,16 +246,13 @@ Recovery process, both manual and automatic, always begins with re-opening AMQP
|
|
283
246
|
|
284
247
|
h3. Manual recovery
|
285
248
|
|
286
|
-
Similarly to the Shutdown Protocol, amqp gem entities implement Recovery Protocol. Recovery Protocol consists of 3 methods
|
287
|
-
connections, channels, queues, consumers and exchanges implement:
|
249
|
+
Similarly to the Shutdown Protocol, amqp gem entities implement Recovery Protocol. Recovery Protocol consists of 3 methods connections, channels, queues, consumers and exchanges implement:
|
288
250
|
|
289
251
|
* {AMQP::Session#before_recovery}
|
290
252
|
* {AMQP::Session#auto_recover}
|
291
253
|
* {AMQP::Session#after_recovery}
|
292
254
|
|
293
|
-
{AMQP::Session#before_recovery} lets application developers register a callback that will be executed *after TCP connection is
|
294
|
-
re-established but before AMQP connection is reopened*. {AMQP::Session#after_recovery} is similar except that the callback is run
|
295
|
-
*after AMQP connection is reopened*.
|
255
|
+
{AMQP::Session#before_recovery} lets application developers register a callback that will be executed *after TCP connection is re-established but before AMQP connection is reopened*. {AMQP::Session#after_recovery} is similar except that the callback is run *after AMQP connection is reopened*.
|
296
256
|
|
297
257
|
{AMQP::Channel}, {AMQP::Queue}, {AMQP::Consumer} and {AMQP::Exchange} methods behavior is identical.
|
298
258
|
|
@@ -316,8 +276,7 @@ Many applications use the same recovery strategy, that consists of the following
|
|
316
276
|
* For each queue, recover all bindings
|
317
277
|
* For each queue, recover all consumers
|
318
278
|
|
319
|
-
amqp gem provides a feature known as "automatic recovery" that is *opt-in* (not opt-out, not used by default) and lets application
|
320
|
-
developers get aforementioned recovery strategy by setting one additional attribute on {AMQP::Channel} instance:
|
279
|
+
amqp gem provides a feature known as "automatic recovery" that is *opt-in* (not opt-out, not used by default) and lets application developers get aforementioned recovery strategy by setting one additional attribute on {AMQP::Channel} instance:
|
321
280
|
|
322
281
|
<pre>
|
323
282
|
<code>
|
@@ -334,15 +293,12 @@ ch = AMQP::Channel.new(connection, AMQP::Channel.next_channel_id, :auto_recovery
|
|
334
293
|
</code>
|
335
294
|
</pre>
|
336
295
|
|
337
|
-
Note that if you do not want to pass any options, 2nd argument can be left out as well,
|
338
|
-
then it will default to {AMQP::Channel.next_channel_id}.
|
296
|
+
Note that if you do not want to pass any options, 2nd argument can be left out as well, then it will default to {AMQP::Channel.next_channel_id}.
|
339
297
|
|
340
298
|
|
341
299
|
To find out whether channel uses automatic recovery mode, use {AMQP::Channel#auto_recovering?}.
|
342
300
|
|
343
|
-
Auto recovery mode can be turned on and off any number of times during channel life cycle, although very small percentage of
|
344
|
-
applications really does this. Typically you decide what channels should be using automatic recovery at application design
|
345
|
-
stage.
|
301
|
+
Auto recovery mode can be turned on and off any number of times during channel life cycle, although very small percentage of applications really does this. Typically you decide what channels should be using automatic recovery at application design stage.
|
346
302
|
|
347
303
|
Full example (run it, then shut down AMQP broker running on localhost, then bring it back up and use management tools such as `rabbitmqctl`
|
348
304
|
to see that queues & bindings & consumer have all recovered):
|
@@ -350,16 +306,14 @@ to see that queues & bindings & consumer have all recovered):
|
|
350
306
|
|
351
307
|
Server-named queues, when recovered automatically, will get *new server-generated names* to guarantee there are no name collisions.
|
352
308
|
|
353
|
-
<span note="
|
354
|
-
When in doubt, try using automatic recovery first. If it is not sufficient for you application, switch to manual
|
355
|
-
recovery using events and callbacks introduced in the "Manual recovery" section.
|
309
|
+
<span note="note">
|
310
|
+
When in doubt, try using automatic recovery first. If it is not sufficient for you application, switch to manual recovery using events and callbacks introduced in the "Manual recovery" section.
|
356
311
|
</span>
|
357
312
|
|
358
313
|
|
359
314
|
h2. Detecting broker failures
|
360
315
|
|
361
|
-
AMQP applications see broker failure as TCP connection loss. There is no reliable way to know whether there is a network split
|
362
|
-
or network peer is down.
|
316
|
+
AMQP applications see broker failure as TCP connection loss. There is no reliable way to know whether there is a network split or network peer is down.
|
363
317
|
|
364
318
|
|
365
319
|
|
@@ -368,9 +322,7 @@ h2. AMQP connection-level exceptions
|
|
368
322
|
|
369
323
|
h3. Handling connection-level exceptions
|
370
324
|
|
371
|
-
Connection-level exceptions are rare and may indicate a serious issue with client library or in-flight data corruption. They mandate
|
372
|
-
that connection cannot be used any more and must be closed. In any case, your application should be prepared to handle this kind of errors.
|
373
|
-
To define a handler, use {AMQP::Session#on_error} method that takes a callback and yields two arguments to it when connection-level exception happens:
|
325
|
+
Connection-level exceptions are rare and may indicate a serious issue with client library or in-flight data corruption. They mandate that connection cannot be used any more and must be closed. In any case, your application should be prepared to handle this kind of errors. To define a handler, use {AMQP::Session#on_error} method that takes a callback and yields two arguments to it when connection-level exception happens:
|
374
326
|
|
375
327
|
<pre>
|
376
328
|
<code>
|
@@ -398,9 +350,7 @@ Full example:
|
|
398
350
|
|
399
351
|
h2. Handling graceful broker shutdown
|
400
352
|
|
401
|
-
When AMQP broker is shut down, it properly closes connection first. To do so, it uses *connection.close* AMQP method. AMQP clients then
|
402
|
-
need to check if the reply code is equal to 320 (CONNECTION_FORCED) to distinguish graceful shutdown. With RabbitMQ, when broker
|
403
|
-
is stopped using
|
353
|
+
When AMQP broker is shut down, it properly closes connection first. To do so, it uses *connection.close* AMQP method. AMQP clients then need to check if the reply code is equal to 320 (CONNECTION_FORCED) to distinguish graceful shutdown. With RabbitMQ, when broker is stopped using
|
404
354
|
|
405
355
|
<pre>rabbitmqctl stop</pre>
|
406
356
|
|
@@ -408,8 +358,7 @@ reply_text will be set to
|
|
408
358
|
|
409
359
|
<pre>CONNECTION_FORCED - broker forced connection closure with reason 'shutdown'</pre>
|
410
360
|
|
411
|
-
Each application choose how to handle graceful broker shutdowns individually, so *amqp gem's automatic reconnection does not cover graceful broker shutdowns*.
|
412
|
-
Applications that want to reconnect when broker is stopped can use {AMQP::Session#periodically_reconnect} like so:
|
361
|
+
Each application choose how to handle graceful broker shutdowns individually, so *amqp gem's automatic reconnection does not cover graceful broker shutdowns*. Applications that want to reconnect when broker is stopped can use {AMQP::Session#periodically_reconnect} like so:
|
413
362
|
|
414
363
|
<pre>
|
415
364
|
<code>
|
@@ -429,9 +378,7 @@ Once AMQP connection is re-opened, channels in automatic recovery mode will reco
|
|
429
378
|
|
430
379
|
h2. Integrating channel-level exceptions handling with object-oriented Ruby code
|
431
380
|
|
432
|
-
Error handling can be easily integrated into object-oriented Ruby code (in fact, this is highly encouraged).
|
433
|
-
A common technique is to combine {http://rubydoc.info/stdlib/core/1.8.7/Object:method Object#method} and {http://rubydoc.info/stdlib/core/1.8.7/Method:to_proc Method#to_proc}
|
434
|
-
and use object methods as error handlers:
|
381
|
+
Error handling can be easily integrated into object-oriented Ruby code (in fact, this is highly encouraged). A common technique is to combine {http://rubydoc.info/stdlib/core/1.8.7/Object:method Object#method} and {http://rubydoc.info/stdlib/core/1.8.7/Method:to_proc Method#to_proc} and use object methods as error handlers:
|
435
382
|
|
436
383
|
<pre>
|
437
384
|
<code>
|
@@ -472,10 +419,9 @@ TBD
|
|
472
419
|
|
473
420
|
h2. AMQP channel-level exceptions
|
474
421
|
|
475
|
-
h3.
|
422
|
+
h3. Handling channel-level exceptions
|
476
423
|
|
477
|
-
Channel-level exceptions are more common than connection-level ones. They are handled in a similar manner, by defining a callback
|
478
|
-
with {AMQP::Channel#on_error} method that takes a callback and yields two arguments to it when channel-level exception happens:
|
424
|
+
Channel-level exceptions are more common than connection-level ones. They are handled in a similar manner, by defining a callback with {AMQP::Channel#on_error} method that takes a callback and yields two arguments to it when channel-level exception happens:
|
479
425
|
|
480
426
|
<pre>
|
481
427
|
<code>
|
@@ -502,13 +448,10 @@ Full example:
|
|
502
448
|
|
503
449
|
h3. Integrating channel-level exceptions handling with object-oriented Ruby code
|
504
450
|
|
505
|
-
Error handling can be easily integrated into object-oriented Ruby code (in fact, this is highly encouraged).
|
506
|
-
A common technique is to combine {http://rubydoc.info/stdlib/core/1.8.7/Object:method Object#method} and {http://rubydoc.info/stdlib/core/1.8.7/Method:to_proc Method#to_proc}
|
507
|
-
and use object methods as error handlers. For example of this, see section on connection-level exceptions above.
|
451
|
+
Error handling can be easily integrated into object-oriented Ruby code (in fact, this is highly encouraged). A common technique is to combine {http://rubydoc.info/stdlib/core/1.8.7/Object:method Object#method} and {http://rubydoc.info/stdlib/core/1.8.7/Method:to_proc Method#to_proc} and use object methods as error handlers. For example of this, see section on connection-level exceptions above.
|
508
452
|
|
509
453
|
<span class="note">
|
510
|
-
Because channel-level exceptions may be raised because of multiple unrelated reasons and often indicate misconfigurations, how they are handled is
|
511
|
-
very specific to particular applications. A common strategy is to log an error and then open and use another channel.
|
454
|
+
Because channel-level exceptions may be raised because of multiple unrelated reasons and often indicate misconfigurations, how they are handled is very specific to particular applications. A common strategy is to log an error and then open and use another channel.
|
512
455
|
</span>
|
513
456
|
|
514
457
|
|
@@ -588,9 +531,7 @@ TBD
|
|
588
531
|
|
589
532
|
h2. Conclusion
|
590
533
|
|
591
|
-
Distributed applications introduce a whole new class of
|
592
|
-
unreliability of the network. The famous "Fallacies of Distributed Computing":http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing list
|
593
|
-
common assumptions software engineers must not make:
|
534
|
+
Distributed applications introduce a whole new class of failures developers need to be aware of. Many of them come from unreliability of the network. The famous "Fallacies of Distributed Computing":http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing list common assumptions software engineers must not make:
|
594
535
|
|
595
536
|
* The network is reliable.
|
596
537
|
* Latency is zero.
|
@@ -601,16 +542,11 @@ common assumptions software engineers must not make:
|
|
601
542
|
* Transport cost is zero.
|
602
543
|
* The network is homogeneous.
|
603
544
|
|
604
|
-
Unfortunately, applications that use Ruby and AMQP are not immune to these problems and developers need to always keep that
|
605
|
-
in mind. This list is just as relevant in 2011 as it was in the 90s.
|
545
|
+
Unfortunately, applications that use Ruby and AMQP are not immune to these problems and developers need to always keep that in mind. This list is just as relevant in 2011 as it was in the 90s.
|
606
546
|
|
607
|
-
Ruby amqp gem 0.8.x and later lets applications to define handlers that handle connection-level exceptions, channel-level
|
608
|
-
exceptions and TCP connection failures. Handling AMQP exceptions and network connection failures is relatively easy.
|
609
|
-
Re-declaring AMQP instances application works with is where the most of complexity comes from. By using Ruby objects as
|
610
|
-
error handlers, declaration of AMQP entities can be done in one place, making it much easier to understand and maintain.
|
547
|
+
Ruby amqp gem 0.8.x and later lets applications to define handlers that handle connection-level exceptions, channel-level exceptions and TCP connection failures. Handling AMQP exceptions and network connection failures is relatively easy. Re-declaring AMQP instances application works with is where the most of complexity comes from. By using Ruby objects as error handlers, declaration of AMQP entities can be done in one place, making it much easier to understand and maintain.
|
611
548
|
|
612
|
-
amqp gem error handling and interruption is not a copy of RabbitMQ Java client's "Shutdown Protocol":http://www.rabbitmq.com/api-guide.html#shutdown,
|
613
|
-
but they turn out to be similar with respect to network failures and connection-level exceptions.
|
549
|
+
amqp gem error handling and interruption is not a copy of RabbitMQ Java client's "Shutdown Protocol":http://www.rabbitmq.com/api-guide.html#shutdown, but they turn out to be similar with respect to network failures and connection-level exceptions.
|
614
550
|
|
615
551
|
TBD
|
616
552
|
|
@@ -623,9 +559,7 @@ This guide was written by "Michael Klishin":http://twitter.com/michaelklishin an
|
|
623
559
|
|
624
560
|
h2. Tell us what you think!
|
625
561
|
|
626
|
-
Please take a moment and tell us what you think about this guide "on Twitter":http://twitter.com/rubyamqp or "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp:
|
627
|
-
what was unclear? what wasn't covered? maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is
|
628
|
-
key to making documentation better.
|
562
|
+
Please take a moment and tell us what you think about this guide "on Twitter":http://twitter.com/rubyamqp or "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp: What was unclear? What wasn't covered? Maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is key to making documentation better.
|
629
563
|
|
630
564
|
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
|
631
565
|
|
data/docs/Exchanges.textile
CHANGED
data/docs/GettingStarted.textile
CHANGED
@@ -2,10 +2,6 @@
|
|
2
2
|
|
3
3
|
h1. Getting started with the Ruby amqp gem
|
4
4
|
|
5
|
-
h2. This Documentation Has Moved to rubyamqp.info
|
6
|
-
|
7
|
-
amqp gem documentation guides are now hosted on "rubyamqp.info":http://rubyamqp.info.
|
8
|
-
|
9
5
|
|
10
6
|
h2. About this guide
|
11
7
|
|
@@ -90,7 +86,7 @@ h3. You can also use Bundler to install the gem
|
|
90
86
|
<code>
|
91
87
|
source :rubygems
|
92
88
|
|
93
|
-
gem "amqp", "~> 0.
|
89
|
+
gem "amqp", "~> 0.9.0" # optionally: :git => "git://github.com/ruby-amqp/amqp.git", :branch => "0.9.x-stable"
|
94
90
|
</code>
|
95
91
|
</pre>
|
96
92
|
|
@@ -105,7 +101,7 @@ irb -rubygems
|
|
105
101
|
:001 > require "amqp"
|
106
102
|
=> true
|
107
103
|
:002 > AMQP::VERSION
|
108
|
-
=> "0.
|
104
|
+
=> "0.9.0"
|
109
105
|
</code>
|
110
106
|
</pre>
|
111
107
|
|
@@ -223,7 +219,7 @@ For the sake of simplicity, both the message producer (App I) and the consumer (
|
|
223
219
|
Now let us move on to a little bit more sophisticated example.
|
224
220
|
|
225
221
|
|
226
|
-
h2.
|
222
|
+
h2. Blabbr: one-to-many publish/subscribe (pubsub) example
|
227
223
|
|
228
224
|
The previous example demonstrated how a connection to a broker is made and how to do 1:1 communication
|
229
225
|
using the default exchange. Now let us take a look at another common scenario: broadcast, or multiple consumers
|
@@ -272,7 +268,7 @@ exchange = channel.fanout("nba.scores")
|
|
272
268
|
</pre>
|
273
269
|
|
274
270
|
The exchange that we declare above using {AMQP::Channel#fanout} is a _fanout exchange_. A fanout exchange delivers messages to all of the queues that
|
275
|
-
are bound to it: exactly what we want in the case of Blabbr
|
271
|
+
are bound to it: exactly what we want in the case of Blabbr.
|
276
272
|
|
277
273
|
This piece of code
|
278
274
|
|
@@ -303,11 +299,11 @@ A diagram for Blabbr looks like this:
|
|
303
299
|
|
304
300
|
|
305
301
|
Next we use EventMachine's {http://eventmachine.rubyforge.org/EventMachine.html#M000466 add_timer} method to
|
306
|
-
run a piece of code in
|
302
|
+
run a piece of code in 2 seconds from now:
|
307
303
|
|
308
304
|
<pre>
|
309
305
|
<code>
|
310
|
-
EventMachine.add_timer(
|
306
|
+
EventMachine.add_timer(2) do
|
311
307
|
exchange.delete
|
312
308
|
|
313
309
|
connection.close { EventMachine.stop }
|
@@ -1,10 +1,7 @@
|
|
1
1
|
# @title Ruby AMQP gem: Patterns and Use Cases
|
2
2
|
|
3
|
-
h1. Patterns and Use Cases
|
4
|
-
|
5
|
-
h2. This Documentation Has Moved to rubyamqp.info
|
6
3
|
|
7
|
-
|
4
|
+
h1. Patterns and Use Cases
|
8
5
|
|
9
6
|
|
10
7
|
h2. About this guide
|