---
feature_story: FS_00_13_77_97
feature_title:  plugin framework
feature_status: TEST
---

# Plugin framework

Plugins are configured under `plugin_instance_entries` in `argrelay_plugin.yaml` config file (see also `PluginConfigSchema.py`).

Both plugin and plugin instance are used interchangeably to mean individual (runtime) plugin instance
identified by `plugin_instance_id` and configured under `plugin_instance_entries`.

Each plugin in configured in one place, but do not confuse (distinguish):
*   `plugin_entry` which `argrelay` uses to manage plugin instances.
*   `plugin_config` (part of `plugin_entry`) which is plugin-specific config (opaque to `argrelay`).

Each plugin entry under `plugin_instance_entries` is defined by `PluginEntrySchema.py`.

Plugins may be configured, but not activated (disabled).

To activate a plugin instance, `plugin_enabled` in its descriptor should be set to `true`.

Plugin instances are activated in the order of DAG (from dependency to dependant)
described by `plugin_dependencies` list.

# Plugin types

There are few `PluginType`-s (see enum):
*   `LoaderPlugin`
*   `InterpFactoryPlugin`
*   `DelegatorPlugin`

`AbstractPlugin` is the base class for all plugins.

# `LoaderPlugin` / `AbstractLoader`

Loader is the simplest plugin.

Data is loaded once on restart.

When func `AbstractLoader.update_static_data` is called, it:
*   Populates `dict`-s into `EnvelopeCollection.data_envelopes` - the data to be searched.
*   Lists field names into `EnvelopeCollection.index_props` - the fields to be indexed by MongoDB.

# `InterpFactoryPlugin` / `AbstractInterpFactory`

Interp factory (short for "interpreter") is a factory instance configured to create `AbstractInterp`.

Classes derived from `AbstractInterp` do all the interesting work:
*   The command line processing loop in `InterpContext.interpret_command` interacts with interps.
*   Interps can be chained by returning `InterpStep`.

Normally, `FuncTreeInterp` is used at the end of the interp chain:
*   Its main task is to consume args and find a func `data_envelope` first.
*   Once func `data_envelope` is found the data from the envelope is used to interpret func args.

See also FS_55_57_45_04 enum selector.

# `DelegatorPlugin` / `AbstractDelegator`

Ultimately, delegators are used to execute the selected func with their args.

They are split into two parts:
*   (dynamic) `AbstractDelegator.run_invoke_control` is used on the server side (to prepare data to send to client).
*   (static) `AbstractDelegator.invoke_action` is used on the client side (to execute command by client).

# Difference between: interp vs delegator

See also: TODO_26_08_72_06: interp vs delegator

| `interp`                                                               | `delegator`                                            |
|------------------------------------------------------------------------|--------------------------------------------------------|
| In practice, common interp implementation searches func via func tree. | Always searches func args (standard search).           |
| In theory, can switch to any command line interpretation (e.g. ML).    | Limited to specific interpretation by standard search. |
| Selected by interp tree.                                               | Selected by func tree.                                 |
|                                                                        |                                                        |
|                                                                        |                                                        |
