Loads and manages hook plugins shipped as OTP applications under modules/plugins/*.
Each plugin is expected to be a directory named after the OTP app name (e.g. my_game_hook)
containing:
modules/plugins/my_game_hook/
ebin/my_game_hook.app
ebin/Elixir.Gamend.Modules.MyGameHook.beam
priv/**
deps/*/ebin/*.beam
deps/*/priv/**The plugin's .app env must include the key :hooks_module, whose value is either a
charlist or string module name like 'Elixir.Gamend.Modules.MyGameHook'.
This manager is intentionally dependency-free: it only adds ebin directories to the code
path and uses Application.load/1 + Application.ensure_all_started/1.
Summary
Functions
How long a hook call may run, in ms: call_timeout_in_transaction_ms inside a
Repo transaction, call_timeout_ms otherwise.
Returns a specification to start this module under a supervisor.
Loads one plugin from disk again and runs its after_startup/0, the
counterpart of suspend/1. Returns the plugin (its status says whether it
started), or nil when the manager is not running or skips the name.
Stops and unloads one plugin, leaving the others running. Returns true
when the manager had it (loaded or failed), false when it did not or the
manager is not running.
Types
Functions
@spec call_timeout_ms() :: pos_integer()
How long a hook call may run, in ms: call_timeout_in_transaction_ms inside a
Repo transaction, call_timeout_ms otherwise.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec hook_modules() :: [{plugin_name(), module()}]
@spec list() :: [Gamend.Hooks.PluginManager.Plugin.t()]
@spec lookup(plugin_name()) :: {:ok, Gamend.Hooks.PluginManager.Plugin.t()} | {:error, term()}
@spec plugins_dir() :: String.t()
@spec reload() :: [Gamend.Hooks.PluginManager.Plugin.t()]
@spec reload_and_after_startup() :: %{ plugins: [Gamend.Hooks.PluginManager.Plugin.t()], after_startup: map() }
@spec resume(plugin_name()) :: Gamend.Hooks.PluginManager.Plugin.t() | nil
Loads one plugin from disk again and runs its after_startup/0, the
counterpart of suspend/1. Returns the plugin (its status says whether it
started), or nil when the manager is not running or skips the name.
@spec start_link(keyword()) :: GenServer.on_start()
@spec suspend(plugin_name()) :: boolean()
Stops and unloads one plugin, leaving the others running. Returns true
when the manager had it (loaded or failed), false when it did not or the
manager is not running.
The in-process build (Gamend.Hooks.PluginBuilder) calls this before it
compiles the plugin in this VM. The compiler treats a module that is already
loaded as available, so a module compiled against a sibling that is still
loaded would take that sibling's old macros and structs; unloading the
plugin first makes the build see only its own new code. resume/1 loads it
back.