Class: AceMQ::AMQP::ConfirmWait Private
- Inherits:
-
Object
- Object
- AceMQ::AMQP::ConfirmWait
- Defined in:
- lib/acemq/amqp/transport.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
bunny's wait_for_confirms, made to let go when the connection is lost.
A message written just as the connection dies is never confirmed, and bunny
never tells the thread waiting for it so. Its recovery does try --
release_all_continuations wakes the waiting thread -- but the wait loops on
an empty continuation queue and goes straight back to sleep, and the same
recovery then replaces that queue with a new one, so no confirm can ever
reach it. The thread sits out bunny's whole continuation timeout, fifteen
seconds by default. Measured on bunny 2.24 and 3.4 alike, with bunny alone
and through this library: a forced close at 86.45s, the connection back at
96.46s, the wait ended by Timeout::Error at 101.46s.
It costs more than the one message, because the wait holds the publish lock: every other publisher on the connection stalled behind it for those fifteen seconds, five of them after the connection was healthy again.
So Transport calls #abandon when a recovery attempt starts, and the waiting thread is told the connection was lost. The message stays a possible loss -- it was written and nothing answered for it -- so the publish fails as unconfirmed, not as declined.
The interruption is Thread#raise, which is only safe because it is fenced
in: it can land only while the thread is inside wait_for_confirms, parked
on a condition variable, and one that arrives as the wait is finishing is
taken here and dropped rather than escaping later from somewhere else. The
earliest bunny offers is before_recovery_attempt_starts, which comes one
network_recovery_interval (5s) after the loss.
Defined Under Namespace
Classes: Abandoned
Instance Method Summary collapse
-
#abandon ⇒ Object
private
Ends the wait in progress, if there is one.
-
#initialize ⇒ ConfirmWait
constructor
private
A new instance of ConfirmWait.
-
#wait(channel) ⇒ Object
private
bunny's answer to "were they all acked", unless #abandon came first.
Constructor Details
#initialize ⇒ ConfirmWait
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of ConfirmWait.
247 248 249 250 |
# File 'lib/acemq/amqp/transport.rb', line 247 def initialize @lock = Mutex.new @waiter = nil end |
Instance Method Details
#abandon ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Ends the wait in progress, if there is one.
268 269 270 271 272 273 274 275 |
# File 'lib/acemq/amqp/transport.rb', line 268 def abandon @lock.synchronize do @waiter&.raise(Abandoned, "the connection was lost while waiting for the broker to confirm " \ "this message, so whether it arrived is unknown") end nil end |
#wait(channel) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
bunny's answer to "were they all acked", unless #abandon came first.
255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/acemq/amqp/transport.rb', line 255 def wait(channel) Thread.handle_interrupt(Abandoned => :never) do @lock.synchronize { @waiter = Thread.current } begin Thread.handle_interrupt(Abandoned => :immediate) { channel.wait_for_confirms } ensure @lock.synchronize { @waiter = nil } discard_late_abandon end end end |