Эликсир - Как убить супервизора, когда связанный процесс убит?

В моем приложении 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 там.

Другие вопросы по тегам