Current section

Files

Jump to
verk lib verk retry_set.ex
Raw

lib/verk/retry_set.ex

defmodule Verk.RetrySet do
@moduledoc """
This module interacts with jobs in the retry set
"""
import Verk.Dsl
alias Verk.SortedSet
alias Verk.Job
@retry_key "retry"
@doc "Redis retry set key"
def key, do: @retry_key
@doc """
Adds a `job` to the retry set ordering by `timestamp`
Optionally a redis connection can be specified
"""
@spec add(%Job{}, integer, GenServer.server) :: :ok | {:error, Redix.Error.t}
def add(job, failed_at, redis \\ Verk.Redis) do
retry_at = calculate_retry_at(failed_at, job.retry_count)
case Redix.command(redis, ["ZADD", @retry_key, to_string(retry_at), Poison.encode!(job)]) do
{:ok, _} -> :ok
{:error, error} -> {:error, error}
end
end
@doc """
Adds a `job` to the retry set ordering by `timestamp`, raising if there's an error
Optionally a redis connection can be specified
"""
@spec add!(%Job{}, integer, GenServer.server) :: nil
def add!(job, failed_at, redis \\ Verk.Redis) do
bangify(add(job, failed_at, redis))
end
defp calculate_retry_at(failed_at, retry_count) do
delay = :math.pow(retry_count, 4) + 15 + (:random.uniform(30) * (retry_count + 1))
failed_at + delay
end
@doc """
Counts how many jobs are inside the retry set
"""
@spec count(GenServer.Server) :: {:ok, integer} | {:error, Redix.Error.t}
def count(redis \\ Verk.Redis), do: SortedSet.count(@retry_key, redis)
@doc """
Counts how many jobs are inside the retry set, raising if there's an error
"""
@spec count!(GenServer.Server) :: integer
def count!(redis \\ Verk.Redis), do: SortedSet.count!(@retry_key, redis)
@doc """
Clears the retry set
It will return `{:ok, true}` if the retry set was cleared and `{:ok, false}` otherwise
An error tuple may be returned if Redis failed
"""
@spec clear(GenServer.server) :: {:ok, boolean} | {:error, Redix.Error.t}
def clear(redis \\ Verk.Redis), do: SortedSet.clear(@retry_key, redis)
@doc """
Clears the retry set, raising if there's an error
It will return `true` if the retry set was cleared and `false` otherwise
"""
@spec clear!(GenServer.server) :: boolean
def clear!(redis \\ Verk.Redis), do: SortedSet.clear!(@retry_key, redis)
@doc """
List jobs from `start` to `stop`
"""
@spec range(integer, integer, GenServer.server) :: {:ok, [Verk.Job.T]} | {:error, Redix.Error.t}
def range(start \\ 0, stop \\ -1, redis \\ Verk.Redis) do
SortedSet.range(@retry_key, start, stop, redis)
end
@doc """
List jobs from `start` to `stop`, raising if there's an error
"""
@spec range!(integer, integer, GenServer.server) :: [Verk.Job.T]
def range!(start \\ 0, stop \\ -1, redis \\ Verk.Redis) do
SortedSet.range!(@retry_key, start, stop, redis)
end
@doc """
Delete the job from the retry set
It returns `{:ok, true}` if the job was found and deleted
Otherwise it returns `{:ok, false}``
An error tuple may be returned if Redis failed
"""
@spec delete_job(%Job{} | String.t, GenServer.server) :: {:ok, boolean}| {:error, Redix.Error.t}
def delete_job(original_json, redis \\ Verk.Redis)
def delete_job(%Job{original_json: original_json}, redis) do
delete_job(original_json, redis)
end
def delete_job(original_json, redis), do: SortedSet.delete_job(@retry_key, original_json, redis)
@doc """
Delete the job from the retry set, raising if there's an error
It returns `true` if the job was found and delete
Otherwise it returns `false`
"""
@spec delete_job!(%Job{} | String.t, GenServer.server) :: boolean
def delete_job!(original_json, redis \\ Verk.Redis)
def delete_job!(%Job{original_json: original_json}, redis) do
delete_job!(original_json, redis)
end
def delete_job!(original_json, redis), do: SortedSet.delete_job!(@retry_key, original_json, redis)
end