It is possible to extend Riptide to support more than simple Mutations and Queries. Riptide Handlers let you define custom commands that can be triggered by the client. It's effectively a simple RPC framework. Handlers can be added to your Riptide configuration.
config :riptide,
handlers: [
Todo.Auth,
Todo.Ping
]
When a command is sent up from the client, every handler in this is called in order until one handles the command.
Clients connect to Riptide over a websocket connection and send commands (either cast or calls) that contain an action and a body. Each connection has state that is passed into the handler when it is triggered by a command. The handler can process the command and choose to update the state. The lifecycle looks very similar to Elixir's GenServer.
handle_call
A call is a command that expects a reply.
defmodule Todo.Auth do
use Riptide.Command
def handle_call("todo.login", %{"email" => email, "password" => password}, state) do
case Todo.User.login(email, password) do
{:ok, user} -> {:reply, true, %{user: user}}
{:error, error} -> {:error, error, state}
end
end
end
The valid responses are
{:reply, reply, next_state}
- Sends the reply to the client and updates the connection state{:error, error, next_state}
- Sends the error to the client and updates the connection state
handle_cast
A cast is a command that does not expect a reply.
defmodule Todo.Ping do
use Riptide.Command
def handle_cast("todo.ping", _body, state) do
Riptide.merge!(["user:info", state.user, "last_seen"], :os.system_time(:millisecond))
{:noreply, state}
end
end
A valid response is
{:noreply, next_state}
- Updates the connection state with next_state