Một job idempotent là job có thể chạy nhiều lần với cùng arguments mà không gây ra kết quả sai — quan trọng vì Sidekiq/Active Job đảm bảo "at least once" delivery, không phải "exactly once".
Không idempotent (nguy hiểm):
ruby
def perform(user_id)
user = User.find(user_id)
user.increment!(:login_count) # chạy 2 lần → đếm sai
ChargeService.charge(user) # charge 2 lần!
endIdempotent (an toàn):
ruby
def perform(order_id)
order = Order.find(order_id)
return if order.paid? # guard: đã xử lý rồi thì bỏ qua
ActiveRecord::Base.transaction do
order.mark_paid!
PaymentGateway.charge(order.payment_token)
end
endKỹ thuật phổ biến: dùng DB unique constraint / Redis lock / upsert để ngăn side effect trùng.