EasyRpc.Plug behaviour (EasyRpc v1.0.0)

Copy Markdown View Source

Defines the contract for EasyRpc middleware plugs.

A plug sits in a pipeline and can inspect, modify, or short-circuit an RPC call. Each plug receives three arguments:

  1. context — an %EasyRpc.Context{} flowing through the pipeline
  2. opts — arbitrary options configured when the plug is added
  3. next — a function that calls the rest of the pipeline

Return value

Every plug must return an %EasyRpc.Context{}. The simplest implementation just delegates to next:

def call(ctx, _opts, next), do: next.(ctx)

To short-circuit (bypass downstream plugs), set ctx.halted = true:

def call(ctx, _opts, _next) do
  cached = Cache.get(cache_key(ctx))
  if cached, do: %{ctx | result: cached, halted: true}, else: next.(ctx)
end

To wrap (do work before and after downstream plugs):

def call(ctx, opts, next) do
  start = System.monotonic_time()
  result = next.(ctx)
  duration = System.monotonic_time() - start
  :telemetry.execute([:easy_rpc, :call], %{duration: duration}, %{})
  result
end

Example — cache plug

defmodule MyCachePlug do
  @behaviour EasyRpc.Plug

  def call(ctx, _opts, next) do
    key = cache_key(ctx)
    case Cachex.get(:rpc_cache, key) do
      {:ok, nil} ->
        result = next.(ctx)
        if result.result, do: Cachex.put(:rpc_cache, key, result.result)
        result

      {:ok, cached} ->
        %{ctx | result: cached, halted: true}
    end
  end

  defp cache_key(ctx), do: {ctx.config.module, ctx.function, ctx.args}
end

Summary

Callbacks

call(context, opts, next)

@callback call(context :: EasyRpc.Context.t(), opts :: term(), next :: function()) ::
  EasyRpc.Context.t()

Invokes the plug.

Receives the current %EasyRpc.Context{}, the plug options, and a next function that runs the remainder of the pipeline. Must return a (possibly modified) %EasyRpc.Context{}.