-
Notifications
You must be signed in to change notification settings - Fork 2
What is a Plugin?
For more information on the Conductor framework, see the Conductor documentation.
In abstract terms, a plugin is a "piece of software" that adds specific feature or functionality to the Conductor framework.
(Excerpted from the Conductor documentation)
- Host: An environment from which Runners may be created, e.g. browser, CLI.
- Runner: An environment where user code is run.
- Evaluator: A program that processes user code and produces the result(s).
- Channel: A named bidirectional data stream between a Host and a Runner.
- Plugin: A program that provides additional functionality, loaded on demand; it may receive communications and communicate on declared Channels.
As mentioned above, the host and runner are transceivers of data which communicate over channels. A host or runner can load and register a plugin. The plugins can then execute code within the environment (host/runner) it was registered on.
Plugins can also attach themselves to channels, so two plugins can communicate over a common channel. A common idiom for plugins is a runner plugin which performs a language-specific execution of data and a host plugin which displays the result.
sequenceDiagram
participant Host
box Channel
participant Host Plugin
participant Runner Plugin
end
participant Runner
Runner->>Runner Plugin: Registers Plugin
Runner Plugin->>Host: Request Host Plugin Load
Host-->>Host Plugin: Registers Plugin
Note over Host Plugin,Runner Plugin: On Execution Start
Host Plugin->>Runner Plugin: Requests Execution
Runner Plugin->>Runner: Requests Execution
Runner-->>Runner Plugin: Returns Result
Runner Plugin-->>Host Plugin: Serializes and Sends Result
Host Plugin->>Host: Displays Result
Fig. 1: Example sequence diagram of a runner-host plugin pair performing an arbitrary execution
In practice, a plugin is a class which implements the IPlugin interface. Each plugin class has a unique ID (e.g., "__runner_cse"). The plugins can attach themselves to channels using the static channelAttach field at initialisation.
An example class (adapted from src/runner/test/src/index.ts is)
import { CHANNEL_ID, RUNNER_ID, type TestMessage } from "@sourceacademy/common-test";
import { IPlugin, IChannel, IConduit } from "@sourceacademy/conductor/conduit";
export class TestPlugin implements IPlugin {
readonly id: string = RUNNER_ID;
static readonly channelAttach = [CHANNEL_ID];
private readonly __testChannel: IChannel<TestMessage>;
constructor(
_conduit: IConduit,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[testChannel]: IChannel<any>[],
) {
this.__testChannel = testChannel;
this.__testChannel.subscribe(message => {
console.log(message);
});
this.__testChannel.send("ping");
}
}As you can see, this plugin is designed to be registered by a runner. It requests a channel with id CHANNEL_ID, and receives it from the constructor. It then sends a "ping" message, and waits for a response