Packages
gen_server_proxy
0.1.64
0.1.72
0.1.71
0.1.70
0.1.68
0.1.67
0.1.66
0.1.65
0.1.64
0.1.63
0.1.62
0.1.61
0.1.60
0.1.59
0.1.58
0.1.57
0.1.56
0.1.55
0.1.54
0.1.53
0.1.52
0.1.51
0.1.50
0.1.49
0.1.48
0.1.47
0.1.46
0.1.45
0.1.44
0.1.43
0.1.42
0.1.40
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
0.1.31
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Invokes call, cast or stop with a GenServer registered via a server ID. Will wait a bit if the GenServer is not yet registered on restarts.
Current section
Files
Jump to
Current section
Files
lib/gen_server/proxy.ex
defmodule GenServer.Proxy do
@moduledoc """
Invokes the following functions with a GenServer registered via a server ID:
- `GenServer.call/3`
- `GenServer.cast/2` (wait not needed as this is async)
- `GenServer.stop/3`
Will wait a bit if the GenServer is not yet registered on restarts.
Note this is an assumption as the GenServer may have never started.
"""
@typedoc "Server ID"
@type server_id :: term
@doc """
Called to convert the `server_id` into a server name.
## Examples
@impl GenServer.Proxy
def server_name(game_name),
do: {:via, Registry, {:registry, game_name}}
@impl GenServer.Proxy
def server_name(game_name),
do: {:global, {GameServer, game_name}}
"""
@callback server_name(server_id) :: GenServer.name()
@doc ~S'''
Called when the server remains unregistered despite waiting a bit.
Should serve to print a relevant message about the failed request.
## Examples
@impl GenServer.Proxy
def server_unregistered(game_name),
do: :ok = IO.puts("Game #{game_name} not started.")
'''
@callback server_unregistered(server_id) :: term
@doc """
Either aliases `GenServer.Proxy` (this module) and requires the alias or
imports `GenServer.Proxy`. In the latter case, you could instead simply
`import GenServer.Proxy`.
## Examples
use GenServer.Proxy, alias: Proxy
use GenServer.Proxy
import GenServer.Proxy
"""
defmacro __using__(options) do
alias = options[:alias]
if alias do
quote do
alias unquote(__MODULE__), as: unquote(alias)
require unquote(alias)
end
else
quote do
import unquote(__MODULE__)
end
end
end
@doc ~S'''
Makes a synchronous call to the GenServer registered via `server_id`.
Will wait a bit if the GenServer is not yet registered on restarts.
The given `module` (or by default `<caller's_module>.GenServerProxy`) should
implement the 2 callbacks of `GenServer.Proxy` (this module).
## Examples
iex> defmodule Game.Engine.GenServerProxy do
iex> @behaviour GenServer.Proxy
iex>
iex> @impl GenServer.Proxy
iex> def server_name(game_name) do
iex> {:global, game_name}
iex> end
iex>
iex> @impl GenServer.Proxy
iex> def server_unregistered(game_name) do
iex> :ok = IO.puts("Game '#{game_name}' not started.")
iex> end
iex> end
iex>
iex> defmodule Game.Server do
iex> use GenServer
iex>
iex> @impl GenServer
iex> def init(init_arg), do: {:ok, init_arg}
iex>
iex> @impl GenServer
iex> def handle_call(:summary, _from, state), do: {:reply, state, state}
iex> end
iex>
iex> defmodule Game.Engine do
iex> use GenServer.Proxy
iex>
iex> alias __MODULE__.GenServerProxy, as: Proxy
iex>
iex> id = "Tic-Tac-Toe"
iex> name = Proxy.server_name(id)
iex> {:ok, _pid} = GenServer.start_link(Game.Server, "XOX", name: name)
iex>
iex> def summary(id), do: call(id, :summary)
iex> end
iex>
iex> Game.Engine.summary("Tic-Tac-Toe")
"XOX"
'''
defmacro call(server_id, request, timeout \\ 5000, module \\ nil) do
if module do
quote bind_quoted: [
server_id: server_id,
request: request,
timeout: timeout,
module: module
] do
GenServer.Proxy.Caller.call(server_id, request, timeout, module)
end
else
quote bind_quoted: [
server_id: server_id,
request: request,
timeout: timeout
] do
GenServer.Proxy.Caller.call(
server_id,
request,
timeout,
__MODULE__.GenServerProxy
)
end
end
end
@doc """
Sends an async request to the GenServer registered via `server_id`.
No need to wait for the GenServer to be registered as this is async.
The given `module` (or by default `<caller's_module>.GenServerProxy`) should
implement the 2 callbacks of `GenServer.Proxy` (this module).
"""
defmacro cast(server_id, request, module \\ nil) do
if module do
quote bind_quoted: [
server_id: server_id,
request: request,
module: module
] do
GenServer.Proxy.Caster.cast(server_id, request, module)
end
else
quote bind_quoted: [server_id: server_id, request: request] do
GenServer.Proxy.Caster.cast(
server_id,
request,
__MODULE__.GenServerProxy
)
end
end
end
@doc """
Synchronously stops the GenServer registered via `server_id`.
Will wait a bit if the GenServer is not yet registered on restarts.
The given `module` (or by default `<caller's_module>.GenServerProxy`) should
implement the 2 callbacks of `GenServer.Proxy` (this module).
"""
defmacro stop(
server_id,
reason \\ :normal,
timeout \\ :infinity,
module \\ nil
) do
if module do
quote bind_quoted: [
server_id: server_id,
reason: reason,
timeout: timeout,
module: module
] do
GenServer.Proxy.Stopper.stop(server_id, reason, timeout, module)
end
else
quote bind_quoted: [
server_id: server_id,
reason: reason,
timeout: timeout
] do
GenServer.Proxy.Stopper.stop(
server_id,
reason,
timeout,
__MODULE__.GenServerProxy
)
end
end
end
end