0

Elm、phoenix、および elixir は私にとってまったく新しいものなので、phoenix チャネルの使用をテストするために、チャネル テスト アプリを簡単なサンプル アプリにしようと考えました。アプリは古い「部品」から作られているため、他のものも含まれていますが、これについてはご容赦ください。

アイデアは、フェニックスエンドポイントへの http 呼び出しを行う複数の genserver があるということです。基本的に、エージェント プロセスに保持されているリストを更新しているだけです。そのリストは、phoenix チャネルを介して Elm アプリに表示されます。目標は、エージェントの状態が複数のプロセスで頻繁に更新されるとどうなるかを確認することでした。

これが私がこれまでに持っているものです。Elm アプリのセットアップを含むフェニックス サイトと、更新を行う genservers を含む別の Elixir アプリがあります。すべてが約 20 秒間正常に動作しますが、チャネル接続が切断され、ブラウザで更新しない限り再確立されません。バックエンドがまだ正常に動作しており、ブラウザー コンソールにもエラーがないことをログから確認できます。それで、ここでの取引は何ですか?チャンネル接続が失われた場合、自動的に再接続するはずだと思っていましたが、なぜ切断されるのでしょうか?

問題はelm-phoenix-socket にあると推測しています。これはelmアプリでセットアップされています:

socketServer : String
socketServer =
    "ws://localhost:4000/socket/websocket"

initPhxSocket : Phoenix.Socket.Socket Msg
initPhxSocket =
    Phoenix.Socket.init socketServer
        |> Phoenix.Socket.withDebug
        |> Phoenix.Socket.on "new:heartbeats" "heartbeats:lobby" ReceiveHeartbeats

バックエンドでブロードキャストが行われる方法は次のとおりです。

defmodule AbottiWeb.ApiController do
  use AbottiWeb.Web, :controller

  def index(conn, _params) do
    beats = AbottiWeb.HeartbeatAgent.get()
    json conn, beats
  end
  def heartbeat(conn, %{"agent" => agent} ) do
    AbottiWeb.HeartbeatAgent.update(agent)
    beats = AbottiWeb.HeartbeatAgent.get()
    AbottiWeb.Endpoint.broadcast("heartbeats:lobby", "new:heartbeats", beats)
    json conn, :ok
  end
end

したがって、本質的に、genserver はそのハートビート エンドポイントに対して常に呼び出しを行っています。私は問題がここにあるとは思わない。問題が存在する別の可能性は、次のようなチャネル設定です。

user_socket.ex:

defmodule AbottiWeb.UserSocket do
  use Phoenix.Socket

  channel "heartbeats:*", AbottiWeb.HeartbeatChannel

  transport :websocket, Phoenix.Transports.WebSocket

  def connect(_params, socket) do
    {:ok, socket}
  end

  def id(_socket), do: nil
end

および heartbeat_channel.ex:

defmodule AbottiWeb.HeartbeatChannel do
  use AbottiWeb.Web, :channel
  require Logger
  def join("heartbeats:lobby", payload, socket) do
    Logger.debug "Hearbeats:lobby joined: #{inspect payload}"
    if authorized?(payload) do
      {:ok, socket}
    else
      {:error, %{reason: "unauthorized"}}
    end
  end

  # Channels can be used in a request/response fashion
  # by sending replies to requests from the client
  def handle_in("ping", payload, socket) do
    {:reply, {:ok, payload}, socket}
  end

  # It is also common to receive messages from the client and
  # broadcast to everyone in the current topic (heartbeats:lobby).
  def handle_in("shout", payload, socket) do
    broadcast socket, "shout", payload
    {:noreply, socket}
  end

  # This is invoked every time a notification is being broadcast
  # to the client. The default implementation is just to push it
  # downstream but one could filter or change the event.
  def handle_out(event, payload, socket) do
    Logger.debug "Broadcasting #{inspect event} #{inspect payload}"
    push socket, event, payload
    {:noreply, socket}
  end

  # Add authorization logic here as required.
  defp authorized?(_payload) do
    true
  end
end

それで、問題は何ですか?それは本当に単純なことだと思います。

わかりました、ソケット転送がタイムアウトしたことがわかりました。しかし、なぜそれを行うのですか?

4

1 に答える 1