phoenix_gen_socket_client v1.0.0 Phoenix.Channels.GenSocketClient behaviour

Communication with a Phoenix Channels server.

This module powers a process which can connect to a Phoenix Channels server and exchange messages with it. Currently, only websocket communication protocol is supported.

The module is implemented as a behaviour. To use it, you need to implement the callback module. Then, you can invoke start_link/5 to start the socket process. The communication with the server is then controlled from that process.

The connection is not automatically established during the creation. Instead, the implementation can return {:connect, state} to try to establish the connection. As the result either handle_connected/2 or handle_disconnected/2 callbacks will be invoked.

To join a topic, join/3 function can be used. Depending on the result, either handle_joined/4 or handle_join_error/4 will be invoked. A client can join multiple topics on the same socket. It is also possible to leave a topic using the leave/3 function.

Once a client has joined a topic, it can use push/4 to send messages to the server. If the server directly replies to the message, it will be handled in the handle_reply/5 callback.

If a server sends an independent message (i.e. the one which is not a direct reply), the handle_message/5 callback will be invoked.

If the server closes the channel, the handle_channel_closed/4 will be invoked. This will not close the socket connection, and the client can continue to communicate on other channels, or attempt to rejoin the channel.

Sending messages over the socket

As mentioned, you can use join/3, push/4, and leave/3 to send messages to the server. All of these functions require the transport information as the first argument. This information is available in most of the callback functions.

Functions will return {:ok, ref} if the message was sent successfully, or {:error, reason}, where ref is the Phoenix ref used to uniquely identify a message on a channel.

Error responses are returned in following situations:

  • The client is not connected
  • Attempt to send a message on a non-joined channel
  • Attempt to leave a non-joined channel
  • Attempt to join the already joined channel

Keep in mind that there’s no guarantee that a message will arrive to the server. You need to implement your own communication protocol on top of Phoenix Channels to obtain such guarantees.

Process structure and lifecycle

The behaviour will internally start the websocket client in a separate child process. This means that the communication runs concurrently to any processing which takes place in the behaviour.

The socket process will crash only if the websocket process crashes, which can be caused only by some bug in the websocket client library. If you want to survive this situation, you can simply trap exits in the socket process, by calling Process.flag(:trap_exit, true) in the init/1 callback. In this case, a crash of the websocket client process will be treated as a disconnect event.

The socket process never decides to stop on its own. If you want to stop it, you can simply return {:stop, reason, state} from any of the callback.

Summary

Functions

Notifies the socket process that the connection has been established

Notifies the socket process about a disconnect

Forwards a received message to the socket process

Pushes a message to the topic

Callbacks

Invoked after the server closes a channel

Invoked after the client has successfully connected to the server

Invoked after the client has been disconnected from the server

Invoked to handle an Erlang message

Invoked if the server has refused a topic join request

Invoked after the client has successfully joined a topic

Invoked when a message from the server arrives

Invoked when the server replies to a message sent by the client

Invoked when the process is created

Types

encoded_message :: binary
handler_response ::
  {:ok, callback_state} |
  {:connect, callback_state} |
  {:stop, reason :: any, callback_state}
message :: %{topic: topic, event: event, payload: payload, ref: ref}
out_payload :: %{optional(String.t | atom) => any}
payload :: %{optional(String.t) => any}
ref :: pos_integer
socket_opts :: [serializer: module, transport_opts: transport_opts]

Functions

join(transport, topic, payload \\ %{})

Specs

join(transport, topic, out_payload) ::
  {:ok, ref} |
  {:error, reason :: any}

Joins the topic.

leave(transport, topic, payload \\ %{})

Specs

leave(transport, topic, out_payload) ::
  {:ok, ref} |
  {:error, reason :: any}

Leaves the topic.

notify_connected(socket)

Specs

notify_connected(GenServer.server) :: :ok

Notifies the socket process that the connection has been established.

notify_disconnected(socket, reason)

Specs

notify_disconnected(GenServer.server, any) :: :ok

Notifies the socket process about a disconnect.

notify_message(socket, message)

Specs

notify_message(GenServer.server, binary) :: :ok

Forwards a received message to the socket process.

push(transport, topic, event, payload)

Specs

push(transport, topic, event, out_payload) ::
  {:ok, ref} |
  {:error, reason :: any}

Pushes a message to the topic.

start_link(callback, transport_mod, arg, socket_opts \\ [], gen_server_opts \\ [])

Specs

start_link(callback :: module, transport_mod :: module, any, socket_opts, GenServer.options) :: GenServer.on_start

Starts the socket process.

Callbacks

handle_channel_closed(topic, payload, transport, callback_state)

Specs

handle_channel_closed(topic, payload, transport, callback_state) :: handler_response

Invoked after the server closes a channel.

handle_connected(transport, callback_state)

Specs

handle_connected(transport, callback_state) :: handler_response

Invoked after the client has successfully connected to the server.

handle_disconnected(reason, callback_state)

Specs

handle_disconnected(reason :: any, callback_state) :: handler_response

Invoked after the client has been disconnected from the server.

handle_info(message, transport, callback_state)

Specs

handle_info(message :: any, transport, callback_state) :: handler_response

Invoked to handle an Erlang message.

handle_join_error(topic, payload, transport, callback_state)

Specs

Invoked if the server has refused a topic join request.

handle_joined(topic, payload, transport, callback_state)

Invoked after the client has successfully joined a topic.

handle_message(topic, event, payload, transport, callback_state)

Invoked when a message from the server arrives.

handle_reply(topic, ref, payload, transport, callback_state)

Invoked when the server replies to a message sent by the client.

init(arg)

Specs

init(arg :: any) ::
  {:connect, url :: String.t, callback_state} |
  {:noconnect, url :: String.t, callback_state} |
  :ignore |
  {:error, reason :: any}

Invoked when the process is created.