defmodule Storex.Socket do
@moduledoc """
Socket connection handler.
Error codes:
- `4000`: Store is not set.
- `4001`: Store is not defined or can't be compiled.
"""
@doc false
def message_handle(%{type: "ping"} = message, state) do
message =
Map.put(message, :type, "pong")
|> Jason.encode!()
{:reply, {:text, message}, state}
end
def message_handle(%{store: nil}, state) do
{:reply, {:close, 4000, "Store is not set."}, state}
end
def message_handle(%{type: "join"} = message, state) do
Module.concat([message.store])
|> Code.ensure_compiled()
|> case do
{:module, _} ->
if Storex.Supervisor.has_store(state.session, message.store) == false do
Storex.Supervisor.add_store(state.session, message.store, message.data)
end
store_state = Storex.Supervisor.get_store_state(state.session, message.store)
message =
Map.put(message, :data, store_state)
|> Map.put(:session, state.session)
|> Jason.encode!()
{:reply, {:text, message}, state}
_ ->
{:reply, {:close, 4001, "Store '#{message.store}' is not defined or can't be compiled."},
state}
end
end
def message_handle(%{type: "mutation", session: session, store: store} = message, state) do
Storex.Supervisor.mutate_store(
message.session,
message.store,
message.data.name,
message.data.data
)
|> case do
{:ok, diff} ->
%{
type: "mutation",
session: session,
store: store,
diff: diff,
request: Map.get(message, :request, nil)
}
{:ok, reply_message, diff} ->
%{
type: "mutation",
session: session,
store: store,
diff: diff,
message: reply_message,
request: Map.get(message, :request, nil)
}
{:error, error} ->
%{
type: "error",
session: session,
store: store,
error: error,
request: Map.get(message, :request, nil)
}
end
|> Jason.encode!()
|> (&{:reply, {:text, &1}, state}).()
end
end