module DeadlockRetry
module_function
def with_retry(max_attempts: 3)
attempts = 0
begin
attempts += 1
yield
rescue ActiveRecord::Deadlocked
raise if attempts >= max_attempts
sleep(rand * 0.05 * attempts)
retry
end
end
end
DeadlockRetry.with_retry do
ApplicationRecord.transaction { Inventory::Reserve.new(sku: 'ABC', quantity: 1).call }
end
Deadlocks happen under load. When the operation is safe to retry, rescue the deadlock exception and retry with jitter. Keep retries bounded and log when it happens.