Amarula.Plugin behaviour (amarula v0.1.0)

View Source

Req-style plugin pipelines for a connection.

A connection has two pipelines, each an ordered list of steps on the Amarula.Conn:

  • send_steps — run over an outgoing message before encryption. Use to check/authorize a send, transform the message, or drop it.
  • recv_steps — run over an incoming message after decryption, before the consumer sees it. Use to translate, filter, or drop it.

A step is fn ctx -> {:cont, ctx} | {:halt, reason}:

  • {:cont, ctx} — continue with the (possibly transformed) ctx;
  • {:halt, reason} — stop the pipeline. On send the message is not sent ({:error, {:halted, reason}} to the caller); on receive it is dropped and never reaches the consumer.

The ctx is a map; both pipelines put the message under :message. Send ctx also carries :to/:profile/:msg_id; receive ctx carries :from/:id/:profile (:id is the message id, for building a MessageKey to react/reply).

A plugin is a module that appends steps via attach/2, Req-style:

defmodule Blocklist do
  def attach(conn, opts \\ []) do
    jids = Keyword.get(opts, :jids, [])
    Amarula.Plugin.on_send(conn, fn
      %{to: to} = ctx -> if to in jids, do: {:halt, :blocked}, else: {:cont, ctx}
    end)
  end
end

Amarula.new(config) |> Blocklist.attach(jids: [...]) |> Amarula.connect()

Implementing the Amarula.Plugin behaviour (@behaviour Amarula.Plugin) is optional — any module with a matching attach/2 works in a pipe.

Summary

Types

A pipeline step.

Callbacks

Attach the plugin's steps to conn, returning the updated conn.

Functions

Append a step to the receive pipeline (after decrypt).

Append a step to the send pipeline (before encrypt).

Run steps over ctx, threading the ctx through each. Returns {:cont, ctx} if all steps continued (with the final, possibly transformed ctx), or {:halt, reason} at the first step that halted (remaining steps don't run).

Types

step()

@type step() :: Amarula.Conn.step()

A pipeline step.

Callbacks

attach(t, keyword)

@callback attach(
  Amarula.Conn.t(),
  keyword()
) :: Amarula.Conn.t()

Attach the plugin's steps to conn, returning the updated conn.

Functions

on_recv(conn, step)

@spec on_recv(Amarula.Conn.t(), step()) :: Amarula.Conn.t()

Append a step to the receive pipeline (after decrypt).

on_send(conn, step)

@spec on_send(Amarula.Conn.t(), step()) :: Amarula.Conn.t()

Append a step to the send pipeline (before encrypt).

run(steps, ctx)

@spec run([step()], map()) :: {:cont, map()} | {:halt, term()}

Run steps over ctx, threading the ctx through each. Returns {:cont, ctx} if all steps continued (with the final, possibly transformed ctx), or {:halt, reason} at the first step that halted (remaining steps don't run).