Defines the core behavior for a Malla service.
Malla.Service is the foundation of the Malla framework. By use Malla.Service,
a module is transformed into a service with features like automatic cluster
discovery, a plugin-based architecture, and compile-time optimized callback chains.
When you use this module at your service module, a number of utility functions are
inserted into your module. They are documented at Malla.Service.Interface.
For comprehensive documentation, please see the guides:
Summary
Types
Options for configuring a service when using Malla.Service.
Functions
Macro that transforms a module into a Malla service.
Adds a new plugin to the service at run-time.
Utility function to register a name for a plugin's child, using Malla.Registry.
Gets a previously registered child with child_via/3
Macro for defining service callbacks.
Deletes a value from service's store table.
Removes a plugin from the service at run-time.
Function used to prepare the node for stop.
Gets a value from service's store table.
Retrieves all implementations of a callback function across plugins.
Returns supervisor PID for a specific plugin children, if defined.
Get current service status.
Get current running status.
Function used to detect if the service is live.
It returns true if the service is in a live state (starting, running, pausing, paused, stopped, stopping).
Function used to detect if the service is ready.
Inserts a value in service's store table.
Inserts a new value in service's store table. Returns false if object already exists.
Updates config for the service at runtime.
Instructs to the service to restart a plugin.
Sets current admin status for the service.
Starts a new service instance.
Stops a service instance.
Types
@type admin_status() :: :active | :pause | :inactive
@type class() :: Malla.class()
@type id() :: Malla.id()
@type running_status() ::
:starting | :running | :pausing | :paused | :stopping | :stopped | :failed
@type service_info() :: %{ id: Malla.id(), vsn: Malla.vsn(), hash: pos_integer(), admin_status: admin_status(), running_status: running_status(), last_status_time: pos_integer(), last_status_reason: term(), last_error: term(), last_error_time: pos_integer() | nil, pid: pid(), node: node(), callbacks: [{atom(), pos_integer()}] }
@type use_opt() :: {:class, Malla.class()} | {:vsn, Malla.vsn()} | {:otp_app, atom()} | {:global, boolean()} | {:paused, boolean()} | {:plugins, [module()]} | {atom(), any()}
Options for configuring a service when using Malla.Service.
Options include:
:class- The service class. Any atom can be used. Not used by Malla but available in metadata.:vsn- Version string. Not used by Malla but available in metadata.:otp_app- If provided, configuration will be fetched from application config and merged.:global- Whether the service is globally visible.:paused- Whether to start in paused state.:plugins- List of plugin modules this services depends on.
Any other key is considered configuration for the service. See Configuration.
Functions
Macro that transforms a module into a Malla service.
This macro inserts required functions, sets up plugin configuration, registers callbacks, and prepares compile-time hooks for building the service structure and dispatch logic.
See use_opt/0 for configuration options.
Adds a new plugin to the service at run-time.
New plugin will be added to the callback chain, taking into account any declared dependency, and starting any declared children.
It will also recalculate the whole callback chain, according to callbacks defined in this new plugin.
Dispatch module will be recompiled, so new callback chain is available immediately.
Options:
:config- Optional keyword list of configuration to merge when adding the plugin. If provided, the config will be merged using theMalla.Plugin.plugin_config_merge/3.
Utility function to register a name for a plugin's child, using Malla.Registry.
You can use child_whereis/3 to find it later.
Gets a previously registered child with child_via/3
Macro for defining service callbacks.
Transforms a function definition into a callback that can be chained
across plugins. The original function is renamed to {name}_malla_service and registered
for the callback system. At compile time, chained dispatch functions are
generated that call implementations in dependency order, supporting
continuation logic.
A Malla callback can return any of the following:
:cont: continues the call to the next function in the call chain.{:cont, [:a, b:]}: continues the call, but changing the parameters used for the next call. in chain. The list of the array must fit the number of arguments.{:cont, :a, :b}: equivalent to {:cont, [:a, :b]}.- any: any other response stops the call chain a returns this value to the caller.
See Callbacks for details.
Deletes a value from service's store table.
See Storage for details.
Removes a plugin from the service at run-time.
Plugin will be removed from plugins chain, and children will be stopped.
It will also recalculate the whole callback chain, according to callbacks defined in this new plugin.
Dispatch module will be recompiled, so new callback chain is available immediately.
Function used to prepare the node for stop.
Callback Malla.Plugins.Base.service_drain/0 is called to allow each plugin to
clean its state, and return :cont if it is ready to stop, or false if it is not.
If all plugins completed the drain, this returns true
and the node can be stopped. If any returned false, this
function returns false and the node should not be yet stopped.
Gets a value from service's store table.
See Storage for details.
Retrieves all implementations of a callback function across plugins.
Returns a list of {callback_name, arity} along the list of modules that implement it, useful for debugging or introspection.
Returns supervisor PID for a specific plugin children, if defined.
@spec get_service_info(Malla.id() | pid(), timeout()) :: {:ok, service_info()} | {:error, term()}
Get current service status.
This is implemented as a call to the service's GenServer.
@spec get_status(Malla.id()) :: running_status() | :unknown
Get current running status.
This is cached so it is very fast, but it could be slightly outdated on service status changes.
Function used to detect if the service is live.
It returns true if the service is in a live state (starting, running, pausing, paused, stopped, stopping).
If the service is in failed or unknown state, returns false, and
external caller is expected to reset this node if this keeps returning false.
Useful in Kubernetes pod health checks.
Function used to detect if the service is ready.
If the service is in running status we call callback Malla.Plugins.Base.service_is_ready?/0.
Any plugin that is not ready should return false, or, if it is ready, :cont to go to next in chain.
For other statuses it will return false. Useful in Kubernetes pod health checks.
Inserts a value in service's store table.
See Storage for details.
Inserts a new value in service's store table. Returns false if object already exists.
See Storage for details.
Updates config for the service at runtime.
This is a very powerful function, and all used plugins need to support it in order to work properly (unless they are not affected by changes).
The new configuration is deep-merged over the previous one by default.
Plugins can customize merge behavior via Malla.Plugin.plugin_config_merge/3.
After the update we will call Malla.Plugin.plugin_updated/3 for existing plugins.
If a plugin does not implement it, it won't notice the update.
Instructs to the service to restart a plugin.
Children supervisor, if started, will be stopped, and Malla.Plugin.plugin_start/2 will be
called again.
@spec set_admin_status(Malla.id(), admin_status(), atom()) :: :ok | {:error, term()}
Sets current admin status for the service.
See above for a detailed description of each status.
Starts a new service instance.
If a non-empty config is provided, it will be deep-merged with the compile-time config.
Plugins can customize this behavior via Malla.Plugin.plugin_config_merge/3.
See Lifecycle for deatils
Stops a service instance.
If the service was started under a supervisor, this could try to restart it.
If you used service module's Malla.Service.Interface.child_spec/1,
restart would be set to :transient so the supervisor will not restart it.