Reputation: 75760
I have an elixir app that uses Oban
to schedule jobs at a time specified by users. For example, users can specify the date and time to send a certain email.
Oban works great at scheduling the job initially, and with other features like uniqueness, but I can't find a sensible way to update the scheduled time of an existing job (when the user wants to edit the task time).
Currently, two approaches come to mind:
job =
Oban.Job
|> where(fragment("args->>'task_id'") == ^task_id)
|> where([j], j.state in ~w[available scheduled])
|> Repo.one()
Oban.cancel_job(TaskWorker, job.id)
job.args
|> TaskWorker.new(schedule_at: new_time)
|> Oban.insert()
Oban.Job
|> where(fragment("args->>'task_id'") == ^task_id)
|> where([j], j.state in ~w[available scheduled])
|> Repo.one()
|> Ecto.Changeset.cast(%{scheduled_at: new_time}, [:scheduled_at])
|> Repo.update()
But I worry that Oban might have its own hooks which do not get called when updating manually or if there's a better way to do this.
Upvotes: 3
Views: 1156
Reputation: 5006
Oban allows for editing scheduled jobs and will react accordingly.
If you look at its implementation, it does a much better job than the usual job queue based on a database.
It actually implements PG_NOTIFY
to keep track of record changes at the database level (which is what any database backed job queue should do).
So, much praise to the author of oban, he has done the best job I have seen in my career on this topic.
Also, if you are coming from Rails / ActiveRecord, the equivalent in Elixir, named Ecto, does not promote the use of the horrid observer pattern (implemented with before_*
, after_*
, etc hooks).
Consequently this fact, or a good whim of the author from oban, caused him to implement change tracking at the proper level.
You can edit those records. Even outside of the application directly in the database.
See also:
Disclaimer: I am not the author of oban, just a fan. That gold medal goes to sorentwo.
Upvotes: 2