Ensuring per user workflow uniqueness

Hi,

Is there a way to ensure that only one workflow will be scheduled per user in a 3-hour window?

Unlike Unique Workflows (no overlap per user) - #4 by sorenone , this is an idempotency/uniqueness question.

I noted in Oban.Pro.Workflow — Oban Pro v1.6.12 that workflow_id must be unique, and tried to set it to “sync-account-transactions #{account.id}”, but that didn’t prevent insertion.

Best,

Yevhenii

Sure! The trick is to put a single job with uniqueness in front of the workflow creation. Here’s an example:

defmodule MyApp.Flow do
  # The worker doesn't normally have unique enabled
  use Oban.Pro.Worker

  alias Oban.Pro.Workflow

  # Gate the workflow behind a job that's unique by the user id
  def invoke(user) do
    %{user_id: user.id}
    |> new(unique: [period: {3, :hours}])
    |> Oban.insert()
  end

  @impl Oban.Pro.Worker
  def process(job) do
    user = MyApp.Repo.get(MyApp.User, job.args["user_id"])

    # Build up the workflow within the invoked job. Using context and cascade purely as an example.
    Workflow.new()
    |> Workflow.put_context(%{user: user})
    |> Workflow.add_cascade(:a, ...)
    |> Workflow.add_cascade(:b, ...)
    |> Workflow.add_cascade(:c, ...)
    |> Oban.insert_all()
  end
end
1 Like

Neat-o! That’s what I call outside the box thinking :brain::+1: