View Source FunServer (FunServer v0.1.2)

FunServer is a GenServer in which instead of passing parameters to GenServer.call/3 or GenServer.cast/2 and then writing the corresponding callbacks with the necessary functionality you pass functions (i.e. handlers).

Essentially FunServer is just a simple wrapper over GenServer, which takes the approach of passing down functions instead of messages.

example

Example

Basically instead of using handle_call or handle_cast callbacks, functions are being passed that get executed in the corresponding callback.

This is an example of a simple FunServer Stack Server.

defmodule Server do
  use FunServer

  def start_link(_args) do
    FunServer.start_link(__MODULE__, handle_init([]), name: __MODULE__)
  end

  def push(value) do
    value
    |> handle_push()
    |> FunServer.async(__MODULE__)
  end

  def pop(value) do
    value
    |> handle_pop()
    |> FunServer.sync(__MODULE__)
  end

  defp handle_init(args) do
    fn -> {:ok, args} end
  end

  defp handle_push(value) do
    fn state ->
      {:noreply, [value | state]}
    end
  end

  defp handle_pop(value) do
    fn _from, [value | new_state] ->
      {:noreply, value, new_state}
    end
  end
end

The callbacks FunServer wraps around are the following:

  • init/1
  • handle_call/3
  • handle_cast/2
  • handle_continue/2

The rest of the callbacks for GenServer can be handled normally:

  • handle_info/2
  • terminate/2
  • code_change/3
  • format_status/2

Link to this section Summary

Functions

Casts all servers locally registered as name at the specified nodes.

Executes an asynchronous call to the server. Works very similar to how a GenServer.cast/2 function works, but instead of passing message which is later handled in a handle_cast/2 callback, a function is passed, which gets evaluated on the server.

Calls all servers locally registered as name at the specified nodes.

Replies to a client.

Starts a FunServer process without links (outside of a supervision tree)

Starts a FunServer process linked to the current 'caller' process.

Synchronously stops the server with the given reason.

Executes a synchronous call to the server and waits for a reply. Works very similar to how a GenServer.call/3 function works, but instead of passing message which is later handled in a handle_call/3 callback, a function is passed, which gets evaluated on the server.

Link to this section Types

@type async_func_handler() :: mfa() | (state() -> async_handler_response())
@type async_handler() :: mfa() | async_func_handler()
Link to this type

async_handler_response()

View Source
@type async_handler_response() ::
  {:noreply, new_state()}
  | {:noreply, new_state(),
     timeout() | :hibernate | {:continue, async_func_handler()}}
  | {:stop, reason(), new_state()}
@type init_handler() ::
  (() -> {:ok, state()}
         | {:ok, state(),
            timeout() | :hibernate | {:continue, async_func_handler()}}
         | :ignore
         | {:stop, reason()})
@type new_state() :: term()
@type reason() :: any()
@type reply() :: term()
@type state() :: term()
@type sync_func_handler() ::
  (from :: GenServer.from(), state() -> sync_handler_response())
@type sync_handler() :: mfa() | sync_func_handler()
Link to this type

sync_handler_response()

View Source
@type sync_handler_response() ::
  {:reply, reply(), new_state()}
  | {:reply, reply(), new_state(),
     timeout() | :hibernate | {:continue, async_func_handler()}}
  | {:noreply, new_state()}
  | {:noreply, new_state(),
     timeout() | :hibernate | {:continue, async_func_handler()}}
  | {:stop, reason(), reply(), new_state()}
  | {:stop, reason(), new_state()}

Link to this section Functions

Link to this function

abcast(nodes \\ [node() | Node.list()], name, request)

View Source
@spec abcast(nodes :: [node()], name :: atom(), request :: term()) :: :abcast

Casts all servers locally registered as name at the specified nodes.

For more information please refer to GenServer.abcast/3

@spec async(handler :: async_handler(), server :: GenServer.server()) :: term()

Executes an asynchronous call to the server. Works very similar to how a GenServer.cast/2 function works, but instead of passing message which is later handled in a handle_cast/2 callback, a function is passed, which gets evaluated on the server.

For additional information please refer to GenServer.cast/2

Link to this function

multi_call(nodes \\ [node() | Node.list()], name, request, timeout \\ :infinity)

View Source
@spec multi_call(
  nodes :: [node()],
  name :: atom(),
  request :: term(),
  timeout :: timeout()
) :: {replies :: [{node(), term()}], bad_nodes :: [node()]}

Calls all servers locally registered as name at the specified nodes.

For more information please refer to GenServer.multi_call/4

@spec reply(from :: GenServer.from(), reply :: term()) :: :ok

Replies to a client.

For more information please refer to GenServer.reply/2

Link to this function

start(module, init_handler, options \\ [])

View Source
@spec start(module :: atom(), init_handler(), options :: GenServer.options()) ::
  {:ok, pid()} | {:error, any()} | :ignore

Starts a FunServer process without links (outside of a supervision tree)

For more information please refer to GenServer.start/3

Link to this function

start_link(module, init_handler, options \\ [])

View Source
@spec start_link(module :: atom(), init_handler(), options :: GenServer.options()) ::
  {:ok, pid()} | {:error, any()} | :ignore

Starts a FunServer process linked to the current 'caller' process.

For more information please refer to GenServer.start_link/3

Link to this function

stop(server, reason \\ :normal, timeout \\ :infinity)

View Source
@spec stop(server :: GenServer.server(), reason :: term(), timeout :: timeout()) ::
  :ok

Synchronously stops the server with the given reason.

For more information please refer to GenServer.stop/3

Link to this function

sync(handler, server, timeout \\ 5000)

View Source
@spec sync(
  handler :: sync_handler(),
  server :: GenServer.server(),
  timeout :: timeout()
) :: term()

Executes a synchronous call to the server and waits for a reply. Works very similar to how a GenServer.call/3 function works, but instead of passing message which is later handled in a handle_call/3 callback, a function is passed, which gets evaluated on the server.

For additional information please refer to GenServer.call/3