Уже 2 недели я пытался провести полный рефакторинг приложения нашей компании Elixir, потому что у нас было слишком много проблем с процессами.
Поэтому я начал с нуля, шаг за шагом выполняя работу.И вот уже почти 3 дня я сталкиваюсь с той же ошибкой, :bad_return
, когда я начинаю работника в супервизоре.Мое дерево процессов выглядит так:
Application
|- MainSupervisor
|- Some workers (Extreme for EventStore, Repo for PostgreSQL, and a stream subscriber for eventstore)
|- AccountStreamSupervisor
|- AccountStreamDispatcher (Supervisor)
|- StreamSubscriber (Worker)
Диспетчер и подписчик имеют функцию start_child
(поэтому они будут использоваться во время выполнения позже)
Я инициализирую свое деревос Supervisor.start_link/2
для каждого руководителя.Приложение, MainSupervisor, AccountStreamSupervisor запускаются без проблем, но когда дело доходит до инициализации AccountStreamDispatcher, у меня появляется эта ошибка :bad_return
.
Трассировка говорит, что init/1
AccountStreamDispatcher является проблемой, потому что она возвращает{:ok, #PID<0.392.0>
(что, согласно документации, хороший ответ).
Я пробовал так много вещей, как изменение start_link
и init
сигнатур методов, изменение дочерних объявлений, всегда одно и то же,Я знаю, что без моего диспетчера все запускалось правильно ...
Вот код:
defmodule MainSupervisor do
use Supervisor
require Logger
def start_link(_args) do
Logger.info("MainSupervisor => Starting...")
result = Supervisor.start_link(__MODULE__, name: :main_supervisor)
case result do
{:ok, _} ->
nil
:ignore ->
Logger.error("Unable start main supervisor because is ignored")
{:error, {:already_started, _}} ->
Logger.error("Unable start main supervisor because is already started")
{:error, {:shutdown, reason}} ->
Logger.error("Unable start main supervisor because #{IO.inspect(reason)}")
{:error, reason} ->
Logger.error("Unable start main supervisor because #{IO.inspect(reason)}")
end
result
end
def init(_) do
Logger.info("MainSupervisor => Initializing...")
event_store_settings = Application.get_env(:extreme, :event_store)
children = [
[...]
%{
id: ViewBuilder.V2.AccountStreamSupervisor,
start: {ViewBuilder.V2.AccountStreamSupervisor, :start_link, []},
type: :supervisor
}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
defmodule AccountStreamSupervisor do
use Supervisor
require Logger
def start_link do
Logger.info("AccountStreamSupervisor => Starting...")
result = Supervisor.start_link(__MODULE__, name: :account_supervisor)
case result do
{:ok, _} ->
nil
:ignore ->
Logger.error("Unable start account stream supervisor because is ignored")
{:error, {:already_started, _}} ->
Logger.error("Unable start account stream supervisor because is already started")
{:error, {:shutdown, reason}} ->
Logger.error("Unable start account stream supervisor because #{IO.inspect(reason)}")
{:error, reason} ->
Logger.error("Unable start account stream supervisor because #{IO.inspect(reason)}")
end
result
end
def init(_) do
Logger.info("AccountStreamSupervisor => Initializing...")
children = [
%{
id: AccountStreamDispatcher,
start: {AccountStreamDispatcher, :start_link, []},
type: :supervisor
}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
def start_child(account_stream_name) do
Logger.debug(
"AccountStreamSupervisor => Start a new child - AccountStreamDispatcher with the name: #{
account_stream_name
}"
)
Supervisor.start_child(:account_supervisor, [])
end
end
defmodule AccountStreamDispatcher do
use Supervisor
require Logger
def start_link do
Logger.debug("AccountStreamDispatcher => Starting...")
result = Supervisor.start_link(__MODULE__, name: :account_dispatcher)
IO.inspect(result)
case result do
{:ok, _} ->
nil
:ignore ->
Logger.error("Unable start dispatcher because is ignored")
{:error, {:already_started, pid}} ->
Logger.debug("Dispatcher is already started with pid #{pid}")
{:error, reason} ->
Logger.error("Unable start dispatcher because #{IO.inspect(reason)}")
end
result
end
def init(_) do
Logger.info("AccountStreamDispatcher => Initializing...")
children = [
%{
id: StreamSubscriber,
start: {StreamSubscriber, :start_link, []},
type: :supervisor
}
]
Supervisor.start_link(children, [strategy: :one_for_one])
end
def start_child(account_stream_name, type, account_id, sub_keys) do
Logger.debug(
"AccountStreamDispatcher => Start a new child - StreamSubscriber with the name: #{
account_stream_name
}"
)
Supervisor.start_child(
:account_dispatcher,
[
%{
stream_name: account_stream_name,
stream_type: type,
account_id: account_id,
sub_keys: sub_keys
}
]
)
end
end
defmodule StreamSubscriber do
use GenServer
require Logger
alias EventHandler.EventHandlerProvider, as: EventHandlerProvider
def start_link(
args = %{
stream_name: name,
stream_type: _type,
account_id: _account_id,
sub_keys: _sub_keys
}
) do
Logger.debug("StreamSubscriber => Starting... (#{name})")
result = GenServer.start_link(__MODULE__, args, name: name)
case result do
{:ok, _} ->
nil
:ignore ->
Logger.error("Unable start process #{name} because is ignored")
{:error, {:already_started, _}} ->
Logger.error("Unable start process #{name} because is already started")
{:error, reason} ->
Logger.error("Unable start process #{name} because #{IO.inspect(reason)}")
end
result
end
def init(%{stream_name: name, stream_type: type, account_id: account_id, sub_keys: sub_keys}) do
Logger.debug("StreamSubscriber => Initializing... (#{name})")
state = %{stream_name: name, stream_type: type, account_id: account_id, sub_keys: sub_keys}
{:ok, _} = EventHandlerProvider.create_handler(type, name, account_id, sub_keys)
{:ok, state}
end
end
Что я делаю не так?