singyeong_plugin v0.1.2 Singyeong.Plugin behaviour View Source

The base plugin behaviour. Your plugin should only have one module implementing this behaviour.

Note that this behaviour is explicitly, intentionally NOT implemented as a GenServer or similar! You are, of course, free to implement all the callbacks in this module as just GenServer.call(me, :whatever), but this is not going to be explicitly supported by this behaviour. The reasoning for this is that it's significantly easier for runtime checks as to whether a callback is implemented or not if the behaviour isn't implemented as a GenServer-like module. Of course, plugin capabilities exist to help deal with this concern, but I find that it's easier to simply not take that risk and enforce a certain implementation style rather than risking potential runtime crashes due to capabilities being claimed without implementation.

Link to this section Summary

Callbacks

Called when a client identifies with the server. The auth string the client sends, as well as the client's IP address, are passed to this function. Note that there is no guarantee of IPv4 vs IPv6 address, and your code should be able to handle both cases.

Behaves like undo/2, but for handle_global_event/3. See the docs for handle_global_event/3 for caveats to be aware of.

Called when this plugin is supposed to handle an event. The events passed to this function are those specified in Manifest.events only. Built-in events will never be passed to this function.

Behaves like handle_event/2, with several caveats

Called when the plugin is first loaded. Returns a list of children to be added to the initial supervision tree.

Provides information about the plugin. This is cached when the plugin is loaded.

Called when this plugin is supposed to undo some stateful changes. Implementations of this function are expected to be impure, and may do more or less whatever they want. The undo_state parameter may be any value, with the exception that a nil undo state will never be passed to this function, for any reason.

Link to this section Types

Link to this type

auth_string()

View Source
auth_string() :: binary()
Link to this type

direction()

View Source
direction() :: :client | :server
Link to this type

frame()

View Source
frame() :: {:text, map()}
Link to this type

payload()

View Source
payload() :: map()
Link to this type

undo_state()

View Source
undo_state() :: any()

Link to this section Callbacks

Link to this callback

auth(auth_string, ip)

View Source (optional)
auth(auth_string(), ip()) :: :ok | :restricted | {:error, binary()}

Called when a client identifies with the server. The auth string the client sends, as well as the client's IP address, are passed to this function. Note that there is no guarantee of IPv4 vs IPv6 address, and your code should be able to handle both cases.

Requires the :auth capability.

Link to this callback

global_undo(binary, direction, undo_state)

View Source (optional)
global_undo(binary(), direction(), undo_state()) :: :ok | {:error, binary()}

Behaves like undo/2, but for handle_global_event/3. See the docs for handle_global_event/3 for caveats to be aware of.

Link to this callback

handle_event(binary, any)

View Source (optional)
handle_event(binary(), any()) ::
  {:next, [frame()], undo_state()}
  | {:next, frame(), undo_state()}
  | {:next, [frame()]}
  | {:next, frame()}
  | :halt
  | {:error, binary(), undo_state()}
  | {:error, binary()}

Called when this plugin is supposed to handle an event. The events passed to this function are those specified in Manifest.events only. Built-in events will never be passed to this function.

Requires the :custom_events capability.

Plugin event handling behaves in a middleware-type fashion. A plugin can choose to pass execution to the next plugin in the chain via :next, halt execution with :halt, or return an error. Returning an error immediately halts execution and unwinds as much as possible. Halting will immediately stop processing of the event, and will not return anything to the client, as it is assumed that the halted execution was not meant to return any side-effects to the client.

On success, this function returns a tuple starting with either :next or :halt

In non-halt cases, the third return element is the undo state. This is some state that the plugin uses to undo any stateful changes it may have made during the processing of this event, such that any error can result in a rollback of stateful changes. Pure functions may simply return nil for the undo state, or just not include it as an element of the tuple. Note that a nil undo state is assumed to mean that this function has nothing to undo, and as such the undo function for this module will never be called if the event handled by this function requires undo! That is, returning an undo state of nil means that your undo function will never be called. The reason for this is simply that the order in which handle_event vs undo is called cannot be guaranteed, and so you cannot rely on strict ordering of these function calls for reliable undo behaviour.

Link to this callback

handle_global_event(binary, direction, payload)

View Source (optional)
handle_global_event(binary(), direction(), payload()) ::
  {:next, payload(), undo_state()}
  | {:next, payload()}
  | :halt
  | {:error, binary(), undo_state()}
  | {:error, binary()}

Behaves like handle_event/2, with several caveats:

  • Undo is handled by global_undo/3.
  • The frame returned should be the same frame as was passed in, with any necessary modifications.
  • A list of frames cannot be returned, only a single frame.
  • This function is called BEFORE the rest of the event processing pipeline.
  • This function is aware of the "directionality" of an event, that is, this function receives an argument telling it whether the direction of the event is to the :client or to the :server. This argument is also passed to global_undo/3.
  • This function is for events only, not all payloads. Payloads such as identify, heartbeat, ... will not ever be passed to this function.
Link to this callback

load()

View Source
load() ::
  {:ok,
   [
     :supervisor.child_spec()
     | {module(), term()}
     | module()
     | Supervisor.child_spec()
   ]}
  | {:ok, []}
  | {:ok, nil}
  | {:error, binary()}

Called when the plugin is first loaded. Returns a list of children to be added to the initial supervision tree.

Provides information about the plugin. This is cached when the plugin is loaded.

Link to this callback

undo(binary, undo_state)

View Source (optional)
undo(binary(), undo_state()) :: :ok | {:error, binary()}

Called when this plugin is supposed to undo some stateful changes. Implementations of this function are expected to be impure, and may do more or less whatever they want. The undo_state parameter may be any value, with the exception that a nil undo state will never be passed to this function, for any reason.