ktayah
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.
Most Liked
sorentwo
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.
Popular in Troubleshooting
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex










