[elixir! #0024] 엔진 덮개 아래'Channel.push`어떻게 작동합니까

2918 단어 elixirphoenix

Phoenix.Channel.push


처음 피닉스 프레임워크를 접했을 때 홈페이지의 강좌에 따라 채팅 페이지를 만들었다.서버는 채널에서 메시지를 방송할 수 있고,push 메시지를 한 사용자에게 보낼 수 있습니다.phoenix는 도대체 어떻게 한 거야?우리 먼저 이 함수의 정의를 보자
  @doc """
  Sends event to the socket.
  The event's message must be a serializable map.
  ## Examples
      iex> push socket, "new_message", %{id: 1, content: "hello"}
      :ok
  """
  def push(socket, event, message) do
    %{transport_pid: transport_pid, topic: topic} = assert_joined!(socket)
    Server.push(transport_pid, topic, event, message, socket.serializer)
  end

우선 assert_joined!/1 함수를 호출해서 그것이 무슨 소용이 있는지 봅시다
  defp assert_joined!(%Socket{joined: true} = socket) do
    socket
  end

  defp assert_joined!(%Socket{joined: false}) do
    raise """
    `push`, `reply`, and `broadcast` can only be called after the socket has finished joining.
    To push a message on join, send to self and handle in handle_info/2, ie:
        def join(topic, auth_msg, socket) do
          ...
          send(self, :after_join)
          {:ok, socket}
        end
        def handle_info(:after_join, socket) do
          push socket, "feed", %{list: feed_items(socket)}
          {:noreply, socket}
        end
    """
  end

원래는 이 socket이 채널에 가입했는지 확인하는 것뿐입니다. 자세한 오류 알림을 되돌려줍니다. join에서push 메시지를 알려주는 것은 아마도 많은 사람들이 이 문제를 제기했기 때문일 것입니다.
socket에서 transport_pid, topic, serializer 함수를 가져온 후 Server.push 함수를 호출했습니다.

Phoenix.Channel.Server.push

  @doc """
  Pushes a message with the given topic, event and payload
  to the given process.
  """
  def push(pid, topic, event, payload, serializer)
      when is_binary(topic) and is_binary(event) and is_map(payload) do

    encoded_msg = serializer.encode!(%Message{topic: topic,
                                              event: event,
                                              payload: payload})
    send pid, encoded_msg
    :ok
  end
  def push(_, _, _, _, _), do: raise_invalid_message()
Server.push 함수는 받은 topic, eventpayload 인코딩을 받아transport에 보냅니다.그렇다면transport는 이 정보들을 어떻게 처리합니까?

cowboy_websocket:handler_loop


클라이언트가 어떤 채널에 가입했을 때 도대체 무슨 일이 일어났는지 잠시 멈추자.클라이언트와 서버의 연결이 이루어지면transport 프로세스를 생성하고, 클라이언트가 특정channel에 가입하면transport 프로세스는channel 프로세스를 생성합니다.클라이언트가 연결을 끊으면transport 프로세스가 죽고 다음 채널 프로세스도 죽는다.그래서 모든 사용자가 가입한 모든 채널은 하나의 %Phoenix.Socket{} 구조체를 저장하는 데 사용되는 독립된 프로세스를 가지고 있다.
Observer를 통해 프로세스에서 실행 중인 함수 tansport 를 찾았습니다.그 후로 카우보이가 메시지를 웹소켓을 통해 클라이언트에게 보냈다.

총결산


phoenix channel의 메시지push 메커니즘은 매우 간단하고 같은 channel을 주목하는 다른 사람들과 관계가 없습니다.프로세스 관계 그림
다음에 우리는 피닉스가 어떻게 소식을 방송하는지 볼 것이다.

좋은 웹페이지 즐겨찾기