Module: AceMQ::AMQP::Patterns::IdempotencyStore
- Defined in:
- lib/acemq/amqp/patterns/idempotency.rb
Overview
Remembers which messages have already been handled.
A store is anything answering two methods:
first_time?(key) # records the key, true when it had not been seen
forget(key) # removes it, so a message that failed can be redone
and, optionally, two more:
confirm(key) # the work is done; start remembering it properly
claim(key) # first_time? with a three-way answer, see {Claim}
A store with claim can tell work in progress from work done, and
idempotent puts the first back rather than accepting it. A
store with only first_time? cannot, and is treated as before: a repeat
is a duplicate.
first_time? has to be atomic. Two consumers handed the same message at
the same moment must not both be told they are first, or the guard has
done nothing except cost a round trip.
confirm is what a store needs when its record outlives the process
that made it. InMemoryIdempotencyStore has no use for one — a crash
wipes it, so a key it holds is a key somebody is working on now. A store
in a database has to tell the two apart, because a key left behind by a
consumer that died has to expire and a key left behind by work that
finished must not. SQLIdempotencyStore answers it; a store that does
not is simply never asked.
A duck type rather than a class to inherit from, because the store somebody actually wants is their own database — ideally the very rows the handler writes, in the same transaction — and asking them to subclass something from a messaging library to get there is asking for the wrong thing.