I don't want active job to drop jobs when they fail. I want to have a chance to fix the failure and then let them re-run. I tried doing this:
class ApplicationJob < ActiveJob::Base
retry_on Exception, attempts: Float::INFINITY
end
but it didn't work. An email job failed and was just discarded. I'm using delayed_job as the implementation.
Any ideas how to do it?
If you are using Delayed::Job, you end up with two retrying mechanisms on top of each other. Active Job, the Rails general implementation, and the Delayed::Job.
For Active::Job you can do:
class ApplicationJob < ActiveJob::Base
retry_on Exception, wait: :exponentially_longer, attempts: Float::INFINITY
end
Without the wait: :exponentially_longer
, you may end up with a lot of jobs trying every 3 seconds.
The behavior of this retrying method can be a bit odd if you are using Delayed::Job. The job runs and seems to succeed but since it fails, ActiveJob creates a new one to run at a later time. Because of that the field attempts
in Delayed::Job remains at 0 and you need to look at the field handler
to see how many times it was run.
One ActiveJob fails for the last time, the exception bubbles up to Delayed::Job which has its own retrying mechanism. Delayed::Job by default retries 25 times and then deletes the job.
To make Delayed Job keep on trying forever, you can create an initialization file config/initializers/delayed_job_config.rb
changing the max_attempts
values:
Delayed::Worker.max_attempts = Float::INFINITY
If you are worried about losing jobs though, the jobs can fail and not be removed by setting:
Delayed::Worker.destroy_failed_jobs = false
which of the two you use, or how you mix them is up to you. Using Delayed::Job's makes the database make a bit more sense, using ActiveJob's means the method can be transported to other implementations.