Module: ConcernsOnRails::Support::UniqueRetry

Defined in:
lib/concerns_on_rails/support/unique_retry.rb

Overview

Bounded retry for writes guarded by a database unique index. The in-Ruby exists? prechecks in Hashable/Tokenizable/Sequenceable are best-effort: two processes can both pass the check and race to the INSERT/UPDATE, and the documented "add a unique index" guarantee then surfaces as ActiveRecord::RecordNotUnique. Wrapping the write here converts that race back into a fresh attempt.

The block MUST generate a fresh candidate value on every attempt — retrying the same value would just fail limit times.

Note: RecordNotUnique carries no column information portably, so a violation on an unrelated unique index (e.g. a unique email) also triggers retries; they are wasted but bounded by limit.

Create-time usage (a before_create can't retry its own save; on Postgres the failed INSERT poisons the surrounding transaction, so retry the whole create from outside any transaction):

ConcernsOnRails::Support::UniqueRetry.with_retries { Invoice.create!(attrs) }

Class Method Summary collapse

Class Method Details

.with_retries(limit: 3) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/concerns_on_rails/support/unique_retry.rb', line 25

def with_retries(limit: 3)
  attempts = 0
  begin
    yield
  rescue ActiveRecord::RecordNotUnique
    attempts += 1
    raise if attempts >= limit

    retry
  end
end