You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Oban任务执行频率超过每分钟一次?

解决Oban中Worker每10-30秒执行的需求

针对Cron插件无法支持高于每分钟执行频率的问题,以下两种非hack式方案均基于Oban原生能力实现,无需切换框架:

方案一:Worker自调度

让Worker在执行完成后自动调度下一次任务,通过随机间隔控制执行频率:

  1. 修改Worker实现,在perform/1末尾添加调度逻辑:
defmodule MyApp.Workers.W1 do
  use Oban.Worker

  @impl true
  def perform(_args) do
    # 原有任务执行代码

    # 生成10-30秒的随机间隔
    schedule_in = :rand.uniform(21) + 10
    # 插入下一次执行的任务
    __MODULE__.new(%{}) |> Oban.insert(schedule_in: schedule_in)

    :ok
  end
end
  1. 初始化触发:在应用启动时(比如application.ex的启动回调中)手动插入一次初始任务,之后Worker会自动循环调度。

方案二:自定义调度插件

编写轻量的Oban插件,集中管理高频任务的调度:

  1. 实现自定义插件:
defmodule MyApp.Plugins.FrequentScheduler do
  use Oban.Plugin

  @impl true
  def start_link(opts) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  @impl true
  def init(opts) do
    workers = Keyword.get(opts, :workers, [])
    schedule_next_run(workers)
    {:ok, workers}
  end

  @impl true
  def handle_info(:schedule_jobs, workers) do
    # 批量插入指定Worker的任务
    Enum.each(workers, fn worker ->
      worker.new(%{}) |> Oban.insert()
    end)

    # 随机10-30秒后触发下一次调度
    schedule_in = :rand.uniform(21) + 10
    schedule_next_run(workers, schedule_in)

    {:noreply, workers}
  end

  defp schedule_next_run(workers, schedule_in \\ 10) do
    Process.send_after(self(), :schedule_jobs, schedule_in * 1000)
  end
end
  1. 在Oban配置中添加该插件:
# .....
    {Oban.Plugins.Cron,
     crontab: [
       # 保留原有Cron任务(如果需要)
     ]},
    {MyApp.Plugins.FrequentScheduler, workers: [MyApp.Workers.W1, MyApp.Workers.W2]},

方案对比

  • 自调度方案:每个Worker独立控制间隔,适合单Worker个性化调度场景,需手动触发初始任务。
  • 自定义插件:集中管理所有高频任务,启动后自动运行,无需额外初始化操作。

内容的提问来源于stack exchange,提问作者Kon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:35:21