Current section

Files

Jump to
honeydew lib honeydew failure_mode retry.ex
Raw

lib/honeydew/failure_mode/retry.ex

defmodule Honeydew.FailureMode.Retry do
alias Honeydew.FailureMode.Move
@moduledoc """
Instructs Honeydew to retry a job `x` times on failure.
## Examples
Retry jobs in this queue 3 times:
Honeydew.queue_spec(:my_queue, failure_mode: {#{inspect __MODULE__}, [times: 3]})
Retry jobs in this queue 3 times and then move to another queue:
Honeydew.queue_spec(:my_queue,
failure_mode: {
#{inspect __MODULE__},
[times: 3, finally: {#{inspect Move}, [queue: :another_queue]}]
}
)
"""
alias Honeydew.FailureMode.Abandon
alias Honeydew.Job
require Logger
@behaviour Honeydew.FailureMode
@impl true
# if everything looks right, validate the 'finally' mode args, too
def validate_args!([times: times, finally: {module, args}]) when is_integer(times)
and times > 0
and is_atom(module)
and is_list(args) do
module.validate_args!(args)
end
def validate_args!([times: times]) when is_integer(times) and times > 0, do: :ok
def validate_args!(args), do: raise ArgumentError, "You provided arguments (#{inspect args}) to the Retry failure mode, it's expecting either [times: times] or [times: times, finally: {module, args}]"
@impl true
def handle_failure(job, reason, [times: times]), do:
handle_failure(job, reason, [times: times, finally: {Abandon, []}])
def handle_failure(%Job{failure_private: nil} = job, reason, [times: times, finally: finally]), do:
handle_failure(%{job | failure_private: times}, reason, finally)
def handle_failure(%Job{failure_private: 0} = job, reason, [times: _times, finally: {final_mode, final_args}]), do:
final_mode.handle_failure(%{job | failure_private: nil}, reason, final_args)
def handle_failure(%Job{queue: queue, from: from, failure_private: tries_left} = job, reason, _args) do
tries_left = tries_left - 1
job = %{job | failure_private: tries_left}
Logger.info "Job failed because #{inspect reason}, retrying #{tries_left} more times, job: #{inspect job}"
queue
|> Honeydew.get_queue
|> GenServer.cast({:nack, job})
# send the error to the awaiting process, if necessary
with {owner, _ref} <- from,
do: send(owner, %{job | result: {:retrying, reason}})
end
end