Class: AceMQ::AMQP::Patterns::Responder

Inherits:
Object
  • Object
show all
Defined in:
lib/acemq/amqp/patterns/request_reply.rb

Overview

A running responder, and the two numbers it keeps.

responder = Patterns.serve(mq, "price.requests") { |m| price(m.payload) }
responder.answered       # requests answered, counted before each reply left
responder.unanswerable   # requests that named nowhere to reply

The same two numbers Java's Responder.answered() and unanswerable() report, with the same promise about when they can be read: never a wait. Both are in place before the first delivery, and #answered is incremented before the reply is published. Code that sleeps before reading one is working around a defect that is not here.

Everything else about it is the consumer underneath, which is what serve used to return: #cancel, #running? and #queue are that consumer's, and #consumer is the consumer itself for anything this does not forward.

Defined Under Namespace

Classes: Counters

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(consumer, counters) ⇒ Responder

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 Responder.



370
371
372
373
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 370

def initialize(consumer, counters)
  @consumer = consumer
  @counters = counters
end

Instance Attribute Details

#consumer ⇒ Object (readonly)

The consumer underneath, for whatever this does not forward.



376
377
378
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 376

def consumer
  @consumer
end

Instance Method Details

#answered ⇒ Object

How many requests were answered, counted before each reply left.

A caller holding a reply can rely on this having counted it: the increment happens before the publish, so there is no interleaving in which the answer is visible and the number is not. The other order reads more naturally and is wrong — it leaves a window where a reply is in the caller's hands and the responder still says nothing has been answered, which is a dashboard reporting an idle service that is demonstrably working.

A publish that fails hands its increment back, so this counts replies that were sent rather than replies that were attempted.

A responder that raised is counted here too, because a Ruby responder answers that request: the failure goes back to the caller in acemq-error and the caller raises AceMQ::AMQP::Patterns::ResponderFailed rather than waiting out its deadline. Java's responder does not reply at all in that case and so does not count it — the divergence is in what the two do with a failure, not in what the counter means. Split the two apart with acemq.consume.total, where the same delivery is acked or rejected.



399
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 399

def answered = @counters.answered

#cancel(timeout: Connection::DRAIN_TIMEOUT) ⇒ Object

Stops serving, draining the requests already in hand.

A request being answered right now has a caller blocked on the other side, and cutting it off turns their call into a timeout.



420
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 420

def cancel(timeout: Connection::DRAIN_TIMEOUT) = @consumer.cancel(timeout: timeout)

#queue ⇒ Object

The queue requests arrive on.



414
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 414

def queue = @consumer.queue

#running? ⇒ Boolean

Whether the broker is still sending this responder requests.

Returns:

  • (Boolean)


411
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 411

def running? = @consumer.running?

#unanswerable ⇒ Object

How many requests arrived naming nowhere to reply, counted before the delivery is settled.

Anything above zero means a caller is publishing where it means to request. Nothing can answer such a request and nothing about redelivering it would make a reply address appear, so it is dead-lettered once rather than looped.



408
# File 'lib/acemq/amqp/patterns/request_reply.rb', line 408

def unanswerable = @counters.unanswerable