= Avoiding duplicate events =

It is pretty burdensome to check if event is already processed,
especially on bulk data moving.  Here's a way how this can be avoided.

First, consumer must make some guarantees:

 * Always have fixed number of threads, with fixed thread_id's.
 * Must process all events on one transaction.  There can be only
 2 states: all processed or none.

If consumer can act that way, then it can turn off dead thread reaping of PgQ,
by giving thread_timeout = 0.  That guarantees that PgQ won't move any events
into retry queue without consumer knowledge.

Consumer itself can tag events for retry, but then it must be able to handle them later.

After setting thread_timeout = 0, there's 2 scenarios:

 * If the PgQ queue and event data handling happen in same database,
 the consumer must simply call pgq.finish_batch() inside the event-processing
 transaction.

 * If the event processing happens in different database, the consumer
 must store the batch_id into destination database, inside the same
 transaction as the event processing happens.

 Only after committing it, consumer can call pgq.finish_batch() in queue database
 and commit that.

 As the batches come in sequence, there's no need to remember full log of batch_id's,
 it's enough to keep the latest batch_id.

 Then at the start of every batch, consumer can check if the batch_id already
 exists in destination database, and if it does, then just tag batch done,
 without processing.

With all this, there's no need for consumer to check for already processed
events.

NB: This assumes the event processing is transaction-able - failures
will be rollbacked.  If event processing includes communication with
world outside database, eg. sending email, such handling won't work.
