Workflow.add_workflow/4 with deps: permanently suspends a sub-workflow's put_context job

Environment

  • Oban Pro: 1.7.6

  • Oban: 2.22.1

Issue

When a sub-workflow built with Workflow.put_context/2 is attached to a parent via add_workflow/4 with a non-empty deps:, the sub-workflow’s :context job gets stuck in suspended forever. Any downstream job that depends on the whole sub-workflow then never runs.

Code snippet to recreate issue:

defmodule MyMod do
  def do_work(_ctx) do
    IO.inspect("Did work")
  end

  def finish_work(_ctx) do
    IO.inspect("Finished work")
  end
end

sub_a =
  Workflow.new(workflow_name: "sub_a")
  |> Workflow.put_context(%{hello: "world"})
  |> Workflow.add_cascade(:work, &MyMod.do_work/1)

sub_b =
  Workflow.new(workflow_name: "sub_b")
  |> Workflow.put_context(%{hello: "world"})
  |> Workflow.add_cascade(:work, &MyMod.do_work/1)

  Workflow.new(workflow_name: "parent")
  |> Workflow.add_workflow(:a, sub_a, deps: [])      # context stays `completed`
  |> Workflow.add_workflow(:b, sub_b, deps: :a)   # context becomes `suspended` — forever
  |> Workflow.add_cascade(:finish, &MyMod.finish_work/1, deps: [:a, :b])
  |> Oban.insert_all()
  # :finish never becomes available, because :b context job is stuck suspended

Oban UI showing workflow stuck on the context step of sub-workflow b:

Root Cause:

Seems to be linked to the logic in oban/pro/workflow.ex:1729, the add_workflow/4 func and how it behaves with a subworkflow that contains put_context and deps, particularily on the conditional:

if deps != [] and meta_deps == [] do
  # ... put_hold(changeset)

This seems to be linked the context job being stuck in the suspended state.

We can currently work around this temporarily by mainly calling Cascade.new and avoiding the use of Workflow.put_context, but a fix would be appreciated.

Thanks for the excellent report and the minimal reproduction. There’s a fix on main and it will be in v1.7.7 later today.