Last active
June 18, 2021 20:12
-
-
Save trbngr/12e45b26749f1438bf641c3e7ac7a6b5 to your computer and use it in GitHub Desktop.
Phoenix Socket Macros
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
locals_without_parens: [handle_message: 2, handle_message: 3], | |
import_deps: [:ecto, :phoenix, :cqrs_tools], | |
inputs: ["*.{ex,exs}", "priv/*/seeds.exs", "{config,lib,test}/**/*.{ex,exs}"], | |
subdirectories: ["priv/*/migrations"] | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule SocketMacro.Commands.DoSomething do | |
use Cqrs.Command | |
# More info: https://hexdocs.pm/cqrs_tools/Cqrs.Command.html | |
alias Phoenix.Socket | |
field :msg, :string | |
field :player, :integer | |
option :socket, Socket, default: nil | |
option :send_message, Function, default: nil | |
@impl true | |
def handle_dispatch(%{player: player_id} = state, opts) do | |
send_message(%{my: "player #{player_id} has done it now."}, opts) | |
{:ok, Map.from_struct(state)} | |
end | |
defp send_message(message, opts) do | |
with %Socket{} = socket <- Keyword.fetch!(opts, :socket), | |
send_message when is_function(send_message, 2) <- Keyword.fetch!(opts, :send_message) do | |
send_message.(socket, message) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule SocketMacro.MixProject do | |
use Mix.Project | |
... | |
defp deps do | |
[ | |
..., | |
# CQRS Tools are macros to make your life managable. | |
{:cqrs_tools, "~> 0.3"} | |
] | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Cqrs.Phoenix.Socket do | |
defmacro __using__(_) do | |
quote do | |
use Phoenix.Socket | |
import Cqrs.Phoenix.Socket, only: [handle_message: 2, handle_message: 3] | |
@before_compile Cqrs.Phoenix.Socket | |
end | |
end | |
defmacro __before_compile__(_env) do | |
quote do | |
# Catch-all handler | |
def handle_msg(_socket, _state, _payload), do: {:disconnect} | |
end | |
end | |
defmacro handle_message(pattern, command_module, opts \\ []) do | |
quote do | |
Cqrs.Guards.ensure_is_command!(unquote(command_module)) | |
def handle_msg(socket, state, payload = unquote(pattern)) do | |
{auth, state} = Map.pop(state, :auth, %{}) | |
# This allows you to define any fields from payload, auth, or state in your command and validate them as needed. | |
attrs = payload |> Map.merge(auth) |> Map.merge(state) | |
opts = Keyword.put(unquote(opts), :socket, socket) | |
Cqrs.BoundedContext.__dispatch_command__!(unquote(command_module), attrs, opts) | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule SocketMacroWeb.UserSocket do | |
# use Phoenix.Socket | |
# Changed to this | |
use Cqrs.Phoenix.Socket | |
alias SocketMacro.Commands.DoSomething | |
defp on_message(_socket, message) do | |
# send_msg(socket, message) | |
IO.puts("sending #{inspect(message)}") | |
end | |
# send_message would probably just be "send_message: &send_msg/2" but this is for illustration that it works. | |
handle_message %{"msg" => "some_action"}, DoSomething, send_message: &on_message/2 | |
@impl true | |
def connect(_params, socket, _connect_info) do | |
{:ok, socket} | |
end | |
@impl true | |
def id(_socket), do: nil | |
end |
Author
trbngr
commented
Jun 18, 2021
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment