Expand description
This crate defines the API between reaction’s core and plugins.
Plugins must be written in Rust, for now.
This documentation assumes the reader has some knowledge of Rust. However, if you find that something is unclear, don’t hesitate to ask for help, even if you’re new to Rust.
To implement a plugin, one has to provide an implementation of PluginInfo, that provides
the entrypoint for a plugin.
It permits to define 0 to n custom stream and action types.
§Note on reaction-plugin API stability
This is the v1 of reaction’s plugin interface.
It’s quite efficient and complete, but it has the big drawback of being Rust-only and tokio-only.
In the future, I’d like to define a language-agnostic interface, which will be a major breaking change in the API. However, I’ll try my best to reduce the necessary code changes for plugins that use this v1.
§Naming & calling conventions
Your plugin should be named reaction-plugin-$NAME, eg. reaction-plugin-postgresql.
It will be invoked with one positional argument “serve”.
reaction-plugin-$NAME serveThis can be useful if you want to provide CLI functionnality to your users, so you can distinguish between a human user and reaction.
§State directory
It will be executed in its own directory, in which it should have write access.
The directory is $reaction_state_directory/plugin_data/$NAME.
reaction’s state_directory
defaults to its working directory, which is /var/lib/reaction in most setups.
So your plugin directory should most often be /var/lib/reaction/plugin_data/$NAME,
but the plugin shouldn’t expect that and use the current working directory instead.
§Communication
Communication between the plugin and reaction is based on remoc, which permits to multiplex channels and remote objects/functions/trait
calls over a single transport channel.
The channels read and write channels are stdin and stdout, so you shouldn’t use them for something else.
remoc builds upon tokio, so you’ll need to use tokio too.
§Errors
Errors during:
- config loading in
PluginInfo::load_config - startup in
PluginInfo::start
should be returned to reaction by the function’s return value, permitting reaction to abort startup.
During normal runtime, after the plugin has loaded its config and started, and before reaction is quitting, there is no rusty way to send errors to reaction. Then errors can be printed to stderr. They’ll be captured line by line and re-printed by reaction, with the plugin name prepended.
A line can start with DEBUG , INFO , WARN , ERROR .
If it starts with none of the above, the line is assumed to be an error.
Example: Those lines:
WARN This is an official warning from the plugin
Freeeee errrooooorrrWill become:
WARN plugin test: This is an official warning from the plugin
ERROR plugin test: Freeeee errrooooorrrPlugins should not exit when there is an error: reaction quits only when told to do so, or if all its streams exit, and won’t retry starting a failing plugin or stream. Please only exit if you’re in a 100% failing state. It’s considered better to continue operating in a degraded state than exiting.
§Getting started
If you don’t have Rust already installed, follow their Getting Started documentation to get rust build tools and learn about editor support.
Then create a new repository with cargo:
cargo new reaction-plugin-$NAME
cd reaction-plugin-$NAMEAdd required dependencies:
cargo add reaction-plugin tokioReplace src/main.rs with those contents:
use reaction_plugin::PluginInfo;
#[tokio::main]
async fn main() {
let plugin = MyPlugin::default();
reaction_plugin::main_loop(plugin).await;
}
#[derive(Default)]
struct MyPlugin {}
impl PluginInfo for MyPlugin {
// ...
}Your IDE should now propose to implement missing members of the PluginInfo trait.
Your journey starts!
§Examples
Core plugins can be found here: https://framagit.org/ppom/reaction/-/tree/main/plugins.
- The “virtual” plugin is the simplest and can serve as a good complete example that links custom stream types and custom action types.
- The “ipset” plugin is a good example of an action-only plugin.
Modules§
- line
- Helper module that permits to use templated lines (ie.
bad password for <ip>), like in Stream’s and Action’scmd. - shutdown
- Helper module that provides structures to ease the quitting process when having multiple tokio tasks.
- time
- This module provides
parse_duration, which parses duration in reaction’s format (ie.6h,3 days)
Structs§
- Action
Config - The config for one Stream of a type advertised by this plugin.
- Action
Impl - Represents an Action handled by a plugin on reaction core’s side.
- Exec
- A trigger of the Action, sent by reaction core to the plugin.
- Hello
- Manifest
- Mandatory announcement of a plugin’s protocol version, stream and action types.
- Plugin
Info Client - Remote client for PluginInfo.
- Plugin
Info ReqReceiver - Request receiver for PluginInfo.
- Plugin
Info Server - Server for PluginInfo taking the target object by value.
- Stream
Config - The config for one Stream of a type advertised by this plugin.
- Stream
Impl - Represents a Stream handled by a plugin on reaction core’s side.
Enums§
- Plugin
Info Req - Request generated by calling a method on PluginInfo.
- Remote
Error - reaction-plugin’s Error type.
- Value
- A clone of
serde_json::Value. Implements From & Intoserde_json::Value.
Traits§
- Plugin
Info - The only trait that must be implemented by a plugin. It provides lists of stream, filter and action types implemented by a dynamic plugin.
Functions§
- main_
loop - The main loop for a plugin.
Type Aliases§
- Line
- Messages passed from the
StreamImplof a plugin to reaction core - Remote
Result