Skip to content

Commit

Permalink
Link queue supervisor and midwife for restarts
Browse files Browse the repository at this point in the history
When a producer crashes it brings the queue's supervisor down with it.
With enough database errors, the producer may crash repeatedly enough to
exhaust restarts and bring down the DynamicSupervisor in charge of all
queues.

Now the supervisor is linked to the midwife to ensure that the midwife
restarts as well, and it restarts all of the queues.
  • Loading branch information
sorentwo committed Sep 10, 2024
1 parent c521a91 commit 5a51cab
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
15 changes: 7 additions & 8 deletions lib/oban.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule Oban do
use Supervisor

alias Ecto.{Changeset, Multi}
alias Oban.{Config, Engine, Job, Midwife, Notifier, Peer, Registry, Sonar, Stager}
alias Oban.{Config, Engine, Job, Notifier, Nursery, Peer, Registry, Sonar, Stager}
alias Oban.Queue.{Drainer, Producer}

@typedoc """
Expand Down Expand Up @@ -465,14 +465,13 @@ defmodule Oban do
def whereis(name), do: Registry.whereis(name)

@impl Supervisor
def init(%Config{plugins: plugins} = conf) do
def init(%Config{name: name, plugins: plugins} = conf) do
children = [
{Notifier, conf: conf, name: Registry.via(conf.name, Notifier)},
{DynamicSupervisor, name: Registry.via(conf.name, Foreman), strategy: :one_for_one},
{Peer, conf: conf, name: Registry.via(conf.name, Peer)},
{Sonar, conf: conf, name: Registry.via(conf.name, Sonar)},
{Midwife, conf: conf, name: Registry.via(conf.name, Midwife)},
{Stager, conf: conf, name: Registry.via(conf.name, Stager)}
{Notifier, conf: conf, name: Registry.via(name, Notifier)},
{Nursery, conf: conf, name: Registry.via(name, Nursery)},
{Peer, conf: conf, name: Registry.via(name, Peer)},
{Sonar, conf: conf, name: Registry.via(name, Sonar)},
{Stager, conf: conf, name: Registry.via(name, Stager)}
]

children = children ++ Enum.map(plugins, &plugin_child_spec(&1, conf))
Expand Down
33 changes: 33 additions & 0 deletions lib/oban/nursery.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Oban.Nursery do
@moduledoc false

use Supervisor

alias Oban.{Config, Midwife, Registry}

@type opts :: [conf: Config.t(), name: GenServer.name()]

@spec start_link(opts()) :: Supervisor.on_start()
def start_link(opts) when is_list(opts) do
Supervisor.start_link(__MODULE__, opts, name: opts[:name])
end

@spec child_spec(opts()) :: Supervisor.child_spec()
def child_spec(opts) do
name = Keyword.fetch!(opts, :name)

%{super(opts) | id: name}
end

@impl Supervisor
def init(opts) do
conf = Keyword.fetch!(opts, :conf)

children = [
{DynamicSupervisor, name: Registry.via(conf.name, Foreman)},
{Midwife, conf: conf, name: Registry.via(conf.name, Midwife)}
]

Supervisor.init(children, max_restarts: 5, max_seconds: 30, strategy: :rest_for_one)
end
end

0 comments on commit 5a51cab

Please sign in to comment.