Class: AceMQ::AMQP::StreamPosition Private
- Inherits:
-
Object
- Object
- AceMQ::AMQP::StreamPosition
- 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.
How far a stream subscription has got, so a recovery carries on from there.
A queue forgets what it delivered, so re-subscribing after a lost connection
takes whatever is left. A stream forgets nothing, and re-subscribing starts
wherever x-stream-offset says -- and bunny re-subscribes with the arguments
the subscription was first made with. A reader that began at first was
handed the whole stream again (500 entries became 900 deliveries in the
reproducer, on bunny 2.24 and 3.4 alike), and one that began at next skipped
everything appended while it was away (50 of 200 never arrived).
So a re-subscribe starts at the oldest offset delivered and not yet settled, or one past the newest settled: what a queue would redeliver, and nothing it would not. Go's transport does the same.
Deliveries from before a recovery are counted no further once it has been worked out where to resume: the new subscription delivers them again, and a handler still finishing an old copy must not move the position past entries the new one has not reached.
Constant Summary collapse
- ARGUMENT =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
"x-stream-offset"
Class Method Summary collapse
-
.for(arguments) ⇒ Object
private
One for a subscription that names a place in a stream, nil for any other.
Instance Method Summary collapse
-
#initialize ⇒ StreamPosition
constructor
private
A new instance of StreamPosition.
-
#resume ⇒ Object
private
Where a re-subscribe starts, or nil when nothing was delivered and the subscription's own starting point still stands.
-
#track(delivery) ⇒ Object
private
The delivery, recorded as pending and settling itself on ack or nack.
Constructor Details
#initialize ⇒ StreamPosition
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 StreamPosition.
826 827 828 829 830 831 |
# File 'lib/acemq/amqp/transport.rb', line 826 def initialize @lock = Mutex.new @pending = Hash.new(0) # offset => deliveries not yet settled @settled = nil # the newest offset settled @generation = 0 end |
Class Method Details
.for(arguments) ⇒ 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.
One for a subscription that names a place in a stream, nil for any other.
824 |
# File 'lib/acemq/amqp/transport.rb', line 824 def self.for(arguments) = (new if arguments.key?(ARGUMENT)) |
Instance Method Details
#resume ⇒ 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.
Where a re-subscribe starts, or nil when nothing was delivered and the subscription's own starting point still stands. Asking twice without a delivery in between gives the same answer, as a recovery that takes more than one attempt does.
861 862 863 864 865 866 867 868 869 870 871 |
# File 'lib/acemq/amqp/transport.rb', line 861 def resume @lock.synchronize do offset = @pending.empty? ? @settled&.+(1) : @pending.keys.min next nil if offset.nil? @pending.clear @settled = offset - 1 @generation += 1 offset end end |
#track(delivery) ⇒ 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.
The delivery, recorded as pending and settling itself on ack or nack. Recorded before the handler sees it and settled before the broker is told, so a recovery at any moment finds it either pending or done.
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 |
# File 'lib/acemq/amqp/transport.rb', line 836 def track(delivery) offset = delivery.headers[ARGUMENT] return delivery unless offset.is_a?(Integer) generation = @lock.synchronize do @pending[offset] += 1 @generation end ack = delivery.on_ack nack = delivery.on_nack delivery.on_ack = lambda do settle(offset, generation) ack&.call end delivery.on_nack = lambda do |requeue| settle(offset, generation) nack&.call(requeue) end delivery end |