Need suggestion to use configured Oban

Hi friends, I have used Oban in a library, and it is defined as a dependency in my umbrella project.
Now I need to create new Periodic Jobs worker, but Oban was configured in the library before, and I do not want to change the library; hence I decided to start a queue manual in one of my init Genserver when I start a server or user sends a request like this:

defmodule MishkaUser.Worker.ExpireTokenWorker do
  use Oban.Worker, queue: :expire_token, max_attempts: 1
  require Logger

  @spec perform(Oban.Job.t()) :: :ok
  def perform(%Oban.Job{}) do
    IO.inspect("this is what is it")
    :ok
  end
end

And for Starting

Oban.start_queue(queue: :expire_token, limit: 10)

As I said, I do not want to change my library config, so how can I declare MishkaUser.Worker.ExpireTokenWorker settings on this particular module as a Periodic Jobs?

For example, something like this:

use Oban.Worker, queue: :expire_token, max_attempts: 1, crontab: [{"*/5 * * * *"}]

Or please give me a suggestion

Thank you in advance

You didn’t write if there’s something not working with your approach and/or if you’re getting any error… it looks like it should be working. What’s the problem?

As I said, I could not be able to run a Periodic Jobs, because I do not know how can run it something like this:

use Oban.Worker, queue: :expire_token, max_attempts: 1, crontab: [{"*/5 * * * *"}]

It is an example from my mind, not a right config, the problem is how can start a Periodic Jobs worker with Oban.start_queue and without changing the config

Ah okay. I don’t know if you can do it. I suspect you may need to update the Oban config, which can be done at runtime with Application.get_env/Application.put_env, then restart Oban application.

If your Oban is a “pro” version, and you do already have Cron set up as Dynamic Cron Plugin, you can however do what you want as it allows you to insert / remove scheduled jobs on the fly: Dynamic Cron Plugin — Oban Pro v0.11.1

But yeah, if you’re locked to the oban provided by library, and it’s not pro, you probably need to update its config and restart it…

This is complicated. Because I once valued it in my library with a timeout and I can not use pro version because it is an open source project.

I’ll wait for the other suggestion, but thank you

Considering how simple the use-case is, you don’t need to dynamically define a periodic schedule for that job. Instead, define the crontab statically in your overall config, leave the job in the default queue (or another queue you are already running), and then check whether it should run from within the worker.

defmodule MishkaUser.Worker.ExpireTokenWorker do
  use Oban.Worker, queue: :default, max_attempts: 1

  @impl Oban.Worker # Don't define a new spec, declare it as an implementation
  def perform(_job) do
    if Application.get_env(:my_app, :expire_token_enabled?) do
      IO.puts("Expire token is enabled")
    end

    :ok
  end
end

From outside your worker, where you were dynamically starting the queue, update the application environment:

Application.put_env(:my_app, :expire_token_enabled?, true)

Dynamically starting Oban supervisors and queues is advanced, and I really recommend using a simpler path until you get things working in your application.

1 Like

As I understood, I do not need to define a new queue for each worker module?

In crontab based on your example, we need to call the function of worker!! But I need 3 or 4 different worker modules.

crontab: [
       {"* * * * *", MyApp.MinuteWorker} # it is not a queue like :default it call a specific module

What I should do for this? I need to run expire token every 24 hours

Really Thank you for all your efforts

No, absolutely not. Queues are for concurrency control

You can have as many entries (workers) as you need in the crontab. If you want something that runs every 24 hours, use 0 0 * * * to run it at midnight.

1 Like