未知注册表:MyApp.Pubsub

Unknown registry: MyApp.Pubsub

背景

我在一个伞式项目中有一个 Phoenix LiveView 应用程序,它基本上是一个 HelloWorld 项目。 In This Phoenix App 很特别,因为它是一个桌面应用程序: https://github.com/elixir-desktop/desktop

我的 Phoenix 应用既不使用 Ecto 也不使用任何 DB,因此我不得不将常用的 PubSub 行添加到 application.ex 中的监督树中。

问题

除了我关闭应用程序时,一切都按预期工作。关闭后出现错误:

12:19:22.507 [error] GenServer #PID<0.553.0> terminating
** (ArgumentError) unknown registry: WebInterface.PubSub
    (elixir 1.13.1) lib/registry.ex:1334: Registry.info!/1
    (elixir 1.13.1) lib/registry.ex:985: Registry.register/3
    (phoenix_pubsub 2.0.0) lib/phoenix/pubsub.ex:117: Phoenix.PubSub.subscribe/3
    (phoenix 1.6.5) lib/phoenix/channel/server.ex:419: Phoenix.Channel.Server.init_join/3
    (phoenix 1.6.5) lib/phoenix/channel/server.ex:378: Phoenix.Channel.Server.channel_join/4
    (phoenix 1.6.5) lib/phoenix/channel/server.ex:298: Phoenix.Channel.Server.handle_info/2
    (stdlib 3.16.1) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.16.1) gen_server.erl:771: :gen_server.handle_msg/6
Last message: {Phoenix.Channel, %{}, {#PID<0.541.0>, #Reference<0.3172133806.691273734.151736>}, %Phoenix.Socket{assigns: %{}, channel: Phoenix.LiveReloader.Channel, channel_pid: nil, endpoint: WebInterface.Endpoint, handler: Phoenix.LiveReloader.Socket, id: nil, join_ref: "4", joined: false, private: %{}, pubsub_server: WebInterface.PubSub, ref: nil, serializer: Phoenix.Socket.V2.JSONSerializer, topic: "phoenix:live_reload", transport: :websocket, transport_pid: #PID<0.541.0>}}
State: #Reference<0.3172133806.691273734.151738>

这是我的 application.ex 文件:

defmodule WebInterface.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

    alias Desktop

  @impl true
  def start(_type, _args) do
    children = [
      WebInterface.Telemetry,
      WebInterface.Endpoint,
      {Phoenix.PubSub, name: WebInterface.PubSub},
      {Desktop.Window,
       [
         app: :web_interface,
         id: WebInterface,
         title: "Web Interface",
         size: {600, 500},
         menubar: WebInterface.MenuBar,
         url: &WebInterface.Endpoint.url/0
       ]}
    ]

    opts = [strategy: :one_for_one, name: WebInterface.Supervisor]
    Supervisor.start_link(children, opts)
  end

  @impl true
  def config_change(changed, _new, removed) do
    WebInterface.Endpoint.config_change(changed, removed)
    :ok
  end
end

这是正在发生的事情的 gif:

我做错了什么?

回答

原来问题出在我的 children 数组中。由于应用程序顺序很重要,我的 PubSub child 应该在端点之前:

    children = [
      WebInterface.Telemetry,
      {Phoenix.PubSub, name: WebInterface.PubSub},
      WebInterface.Endpoint,
      {Desktop.Window,
       [
         app: :web_interface,
         id: WebInterface,
         title: "Web Interface",
         size: {600, 500},
         menubar: WebInterface.MenuBar,
         url: &WebInterface.Endpoint.url/0
       ]}
    ]