Im running into an issue with Oban where it will just stop processing jobs, even though they are marked as available in the database. I have an hourly recurring job (not through Cron) that will stop after the first time it is processed. I am able to reproduce this 100% of the time.
Edit: Dropping the time to 5 minutes instead of 1 hour causes the issue to not happen, at least quickly enough for me to notice.
This stops processing of all jobs in that queue (I only have a single type of job so I don’t know if all queues are stopped).
Its a standard Phoenix App. The only non-standard part of my setup is that I am using TimescaleDB as the database.
Code for the worker:
defmodule OldSchoolSnitch.Workers.HiScoreWorker do
alias OldSchoolSnitch.Runescape
require Logger
@one_hour 60 * 60
use Oban.Worker,
queue: :hiscores,
unique: [fields: [:args, :worker], states: [:available, :scheduled], period: @one_hour]
@impl Oban.Worker
def perform(%Oban.Job{
args: %{"runescape_name" => runescape_name, "player_id" => player_id} = args,
attempt: 1
}) do
args
|> new(schedule_in: @one_hour)
|> Oban.insert!()
do_job(runescape_name, player_id)
end
def perform(%Oban.Job{
args: %{"runescape_name" => runescape_name, "player_id" => player_id} = _args
}) do
do_job(runescape_name, player_id)
end
defp do_job(runescape_name, player_id) do
Logger.debug("Running hi score job for #{runescape_name}")
hi_scores = Runescape.HiScoresClient.get_hiscores(runescape_name)
db_totals = Runescape.XPDrop.get_users_skill_totals(player_id)
Enum.map(hi_scores, fn x ->
skill = get_db_total_for_skill(db_totals, x.skill)
case skill do
nil ->
%{
player_id: player_id,
skill: x.skill,
amount: 0,
current_total: x.experience
}
|> Runescape.XPDrop.create_xp_drop()
_ ->
if x.experience > skill.current_total do
{:ok, drop} =
%{
player_id: player_id,
skill: x.skill,
amount: x.experience - skill.current_total,
current_total: x.experience
}
|> Runescape.XPDrop.create_xp_drop()
OldSchoolSnitchWeb.Endpoint.broadcast(drop.player_id, "step", drop)
end
end
end)
:ok
end
defp get_db_total_for_skill(db_totals, skill) do
Enum.find(db_totals, fn x ->
x.skill == skill
end)
end
end