cronelixirphoenix-frameworkelixir-oban

How to make Oban run more frequently than once in a minute?


I'm using Oban for the ongoing tasks.

# .....
    {Oban.Plugins.Cron,
     crontab: [
       {"* * * * *", MyApp.Workers.W1},
       {"* * * * *", MyApp.Workers.W2},
     ]},

I now need to run W1 and W2 more frequently that every minute - around once in every 10...30 seconds. Since cron doesn't support higher frequency than 1/min, how would I get around this limitation? Preferably without hacks, unless absolutely necessary.

I don't consider switching from Oban to other library.


Solution

  • I don't believe Oban.Plugins.Cron supports granularity finer than one minute, by glancing at the current code.

    One way you could do this is by having a process (like a GenServer) in your application that uses Process.send_after/3 or :timer.send_interval/2 to periodically queue the Oban jobs you want. This is essentially what Oban.Plugins.Cron is doing. You'll probably want to pay attention to making sure the jobs are unique (documentation).

    Some very simplified code:

    defmodule MyApp.Scheduler do
      use GenServer
    
      def start_link(_) do
        GenServer.start_link(__MODULE__, :no_args)
      end
    
      @impl true
      def init(:no_args) do
        :timer.send_interval(:timer.seconds(30), {:schedule_job, MyApp.Workers.W1, 30})
        :timer.send_interval(:timer.seconds(20), {:schedule_job, MyApp.Workers.W2, 20})
        {:ok, :no_state}
      end
    
      @impl true
      def handle_info({:schedule_job, worker, unique_seconds}, state) do
        %{my: :params}
        |> Oban.Job.new(worker: worker, unique: [period: unique_seconds])
        |> Oban.insert!()
    
        {:noreply, state}
      end
    end