Hi there, oban question here. I’m trying to schedule a weekly job for each user. This job should only be inserted once per user (per week). On the first attempt, the job will reschedule itself for the next week. My problem is that this job is inserted many times, probably due to incorrect unique
options.
Worker code:
defmodule MyApp.WeeklyWorker do
use Oban.Worker,
queue: :events,
unique: [fields: [:args, :worker], states: [:available, :scheduled], period: 60],
max_attempts: 3
@one_week 60 * 60 * 24 * 7
@impl Oban.Worker
def perform(%Oban.Job{args: %{"user_id" => user_id} = args, attempt: 1}) do
args
|> new(schedule_in: @one_week)
|> Oban.insert!()
do_heavy_stuff(user_id)
:ok
end
def perform(%Oban.Job{args: %{"user_id" => user_id} = _args}) do
do_heavy_stuff(user_id)
:ok
end
def do_heavy_stuff(user_id) do
# lots of things...
end
end
This worker should be inserted when the user does a certain update action on an Item
for the first time, so I’ve opted for inserting the weekly job from the corresponding ItemController
action, thinking that the job would be inserted only once, no matter how many times the user would call this action:
def update(%Plug.Conn{assigns: %{current_user: %{id: user_id}}} = conn, %{"id" => id, "item" => item_params}) do
with %UserData.Item{user_id: ^user_id} = item <- UserData.get_item(id),
{:ok, item} <- UserData.rate_item(item, item_params),
{:ok, _job} <- Oban.insert(MyApp.WeeklyWorker.new(%{user_id: user_id}))
do
render(conn, "show.json", item: item)
else
{:error, changeset} -> {:error, changeset}
_item -> {:error, :not_found}
end
end
But unfortunately this is not working; I can see that the WeeklyWorker
is inserted and scheduled more than once (per user, per week). It’s probably due to incorrect unique
options, but I can’t seem to get them right…
Does the unique period
has to be changed to one week? If so, how can this be tested (with ex_unit) to function correctly (or do I just trust oban here)?
Thank you for your time!