Эликсир - Как убить супервизора, когда связанный процесс убит?
В моем приложении Elixir у меня есть два приложения под названием market_manager
а также candle_manager
.
В приложении candle_manager
, У меня есть эта древовидная структура:
В приложенииmarket_manager
, У меня есть такой:
MarketManager.ManagersSupervisor
это динамический руководитель, который может запускать менеджеров. Когда я начинаюManager
, Я получаю следующее:
Кроме того, начатый мной менеджер запустит нового ребенка вCandleManager.Bitfinex.RealtimeSupervisor
называется CandleManager.Bitfinex.Realtime.Supervisor
:
CandleManager.Bitfinex.Realtime.Supervisor
начинается с :temporary
перезапуск, и его PID связан с Manager
один через Process.link
.
Так, например, если Manager
имеет PID <0.612.0>
а также CandleManager.Bitfinex.Realtime.Supervisor
PID <0.613.0>
между этими двумя будет связь (я могу подтвердить через :observer
).
Теперь, если я пойду в :observer
и убить CandleManager.Bitfinex.Realtime.Supervisor
, тогда Manager
получит сообщение о выходе и тоже убьет себя (как и ожидалось).
Но если я убью Manager
вместо, CandleManager.Bitfinex.Realtime.Supervisor
не убит и Manager
не будет перезапущен, так как он попытается начать новый CandleManager.Bitfinex.Realtime.Supervisor
и потерпеть неудачу с :already_started
ошибка.
Итак, мой вопрос: Process.link
правильно работать с Supervisors
? Как я могу сделатьCandleManager.Bitfinex.Realtime.Supervisor
убить себя, когда Manager
убит?
Для полноты картины вот CandleManager.Bitfinex.Realtime.Supervisor
код, в нем нет ничего необычного, что я мог бы увидеть, нарушая Process.link
логика.
defmodule CandleManager.Bitfinex.Realtime.Supervisor do
use Supervisor
alias CandleManager.Bitfinex.Realtime
require Logger
def start_link(args) do
Supervisor.start_link(__MODULE__, args, name: __MODULE__)
end
@impl Supervisor
def init([market_manager_pid: _pid] = args) do
childrens = [
{Realtime.Websocket.Server, []},
{Realtime.Manager.Server, []},
{Realtime.TradeToCandle.Server, []},
{Realtime.TradeDiscarder.Server, args}
]
Supervisor.init(childrens, strategy: :one_for_all, max_restarts: 0)
end
end
Благодарность!
1 ответ
Но если я убью
Manager
вместо,CandleManager.Bitfinex.Realtime.Supervisor
не убит [...]
Вы пытаетесь разорвать контракты OTP, а OTP, очевидно, делает все возможное, чтобы вы не прострелили себе ногу.
DynamicSupervisor
был специально создан, чтобы пережить детские аварии.
он попытается начать новый
CandleManager.Bitfinex.Realtime.Supervisor
и потерпеть неудачу с:already_started
ошибка
:already_started
ответ ни в коем случае не является ошибкой. Это признак того, что процесс уже был запущен раньше и все готово.
делает
Process.link/1
правильно работать сSupervisor
с?
Несомненно. Но обычно при построении деревьев надзора OTP не вызываетсяProcess.link/1
напрямую, все это делается правильно child_specs passed through
.
К сожалению, это все, что я могу сказать до сих пор, поскольку вы не предоставили MCVE и ссылаетесь на имена, не упомянутые нигде на снимках экрана или в коде.
Попробуйте назвать своих руководителей соответствующим образом, нарисуйте дерево на бумаге и внедрите его в код, предоставив соответствующие списки child_specs
за children
во всех соответствующих звонках Supervisor.init/1
. Вам вряд ли понадобится звонитьProcess.link/1
вручную, и я сомневаюсь, что вам действительно нужен DynamicSupervisor
там.