Jobs Must Be Idempotent
Learn about how background tasks can be retried seamlessly without encountering issues due to errors.
We'll cover the following...
Ensuring idempotency in background jobs
One of the reasons we use background jobs is to allow them to be retried automatically when a transient error occurs. While we could build up a list of transient errors and only retry them, this turns out to be difficult, because there are a lot of errors that one would consider transient. It is easier to configure our jobs to automatically retry all errors.
This means that code executed from a job must be idempotent: it must not have its effect felt more than once, no matter how many times it’s executed. Consider this code that updates a widget’s updated_at
.
def touch(widget)
widget.updated_at = Time.zone.now
widget.save!
end
Each time this is called, the widget’s updated_at
will get a new value. That means this method is not idempotent. To make it idempotent, we would need to pass in the date:
def touch(widget, updated_at)
widget.updated_at = updated_at
widget.save!
end
Now, no matter how many times we call touch with the same arguments, the effect will be the same.
The code initiated by our jobs must work similarly. Consider a job that charges someone money ...