mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
A handler that only updates gauges has nothing to yield. collect() already dropped undefined results at runtime, now its type says so too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
162 lines
5.3 KiB
TypeScript
162 lines
5.3 KiB
TypeScript
import type Host from "./Host.js";
|
|
|
|
import * as lib from "@clusterio/lib";
|
|
|
|
export type HostPluginContext = lib.PluginLoadContext<{
|
|
host: Host;
|
|
}>;
|
|
|
|
/**
|
|
* Collection of host plugin hooks
|
|
*/
|
|
export class HostHooks extends lib.AsyncHookCollection {
|
|
constructor(logger: lib.Logger) {
|
|
super(logger);
|
|
this.metrics = this.newHook();
|
|
this.shutdown = this.newHook();
|
|
this.hostConfigFieldChanged = this.newHook();
|
|
this.controllerConnectionEvent = this.newHook();
|
|
this.prepareControllerDisconnect = this.newHook();
|
|
}
|
|
|
|
/**
|
|
* Called when the value of a host config field changed.
|
|
*
|
|
* Invoked after the value of the config field given by `field` has
|
|
* changed on this host.
|
|
*
|
|
* @param field - Name of the field that changed.
|
|
* @param curr - The current value of the field.
|
|
* @param prev - The previous value of the field.
|
|
*/
|
|
readonly hostConfigFieldChanged: lib.AsyncHook<[field: string, curr: unknown, prev: unknown]>;
|
|
|
|
/**
|
|
* Called before collecting Prometheus metrics
|
|
*
|
|
* Invoked before the default metrics of prometheus is collected. Note
|
|
* that since this is done while replying to /metrics this should not
|
|
* take a long time, otherwise the requst will time out.
|
|
*
|
|
* Although you can return the results of collecting your prometheus
|
|
* collectors directly, all gauges in the default registry is already
|
|
* automatically collected. It's therefore recommended to only update
|
|
* the Gauges/Counters/etc in onMetric and let Clusterio deal will
|
|
* collecting the values.
|
|
*
|
|
* @returns an async iterator of prometheus metric results or undefined.
|
|
*/
|
|
readonly metrics: lib.AsyncHook<[], AsyncIterable<lib.CollectorResult> | void>;
|
|
|
|
/**
|
|
* Called when the host is shutting down
|
|
*/
|
|
readonly shutdown: lib.AsyncHook<[]>;
|
|
|
|
/**
|
|
* Called when an event on the controller connection happens
|
|
*
|
|
* The event param may be one of connect, drop, resume and close and has
|
|
* the following meaning:
|
|
*
|
|
* ##### connect
|
|
*
|
|
* Invoked when a new connection to the controller has been established.
|
|
*
|
|
* ##### drop
|
|
*
|
|
* Invoked when a connection loss is detected between the host and the
|
|
* controller. Plugins should respond to this event by throtteling messages
|
|
* it is sending to the controller to an absolute minimum.
|
|
*
|
|
* Messages sent over a dropped controller connection will get queued up in
|
|
* memory on the host and sent all in one go when the connection is
|
|
* re-established again.
|
|
*
|
|
* ##### resume
|
|
*
|
|
* Invoked when the connection that had previously dropped is
|
|
* re-established.
|
|
*
|
|
* ##### close
|
|
*
|
|
* Invoked when the connection to the controller has been closed. This
|
|
* typically means the controller has shut down. Plugins should not
|
|
* send any messages that goes to or via the controller after the
|
|
* connection has been closed and before a new one is established.
|
|
*
|
|
* @param event - one of connect, drop, resume and close
|
|
*/
|
|
readonly controllerConnectionEvent: lib.AsyncHook<[event: "connect" | "drop" | "resume" | "close"]>;
|
|
|
|
/**
|
|
* Called when the controller is preparing to disconnect from the host
|
|
*
|
|
* Invoked when the controller has requested the disconnection from
|
|
* the host. This typically happens when it is in the process of
|
|
* shutting down.
|
|
*
|
|
* Plugins must stop sending messages to the controller, or are forwarded
|
|
* via the controller after the prepare disconnect has been handled.
|
|
*
|
|
* @param connection -
|
|
* The connection to the host preparing to disconnect.
|
|
*/
|
|
readonly prepareControllerDisconnect: lib.AsyncHook<[connection: Host]>;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
export interface BaseHostPlugin {
|
|
onHostConfigFieldChanged?(field: string, curr: unknown, prev: unknown): Promise<void>;
|
|
onMetrics?(): Promise<void | AsyncIterable<lib.CollectorResult>>;
|
|
onShutdown?(): Promise<void>;
|
|
onControllerConnectionEvent?(event: "connect" | "drop" | "resume" | "close"): void;
|
|
onPrepareControllerDisconnect?(connection: Host): Promise<void>;
|
|
}
|
|
|
|
/**
|
|
* Base class for host plugins
|
|
*
|
|
* Host plugins are subclasses of this class which get instantiated by
|
|
* the host when it starts up with the plugin enabled in the config. To be
|
|
* discovered the class must be exported under the name `HostPlugin` in the
|
|
* module specified by the `hostEntrypoint` in the plugin's `plugin` export.
|
|
*/
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
export class BaseHostPlugin {
|
|
constructor(
|
|
public info: lib.PluginNodeEnvInfo,
|
|
public host: Host,
|
|
public logger: lib.Logger,
|
|
) {
|
|
const attach = <Args extends unknown[], Return>(
|
|
hook: lib.AsyncHook<Args, Return>,
|
|
fn?: lib.HookHandler<Args, Return>,
|
|
) => {
|
|
if (fn) {
|
|
hook.attach(info.name, fn.bind(this));
|
|
}
|
|
};
|
|
|
|
attach(host.hooks.hostConfigFieldChanged, this.onHostConfigFieldChanged);
|
|
attach(host.hooks.metrics, this.onMetrics);
|
|
attach(host.hooks.shutdown, this.onShutdown);
|
|
attach(host.hooks.controllerConnectionEvent, this.onControllerConnectionEvent);
|
|
attach(host.hooks.prepareControllerDisconnect, this.onPrepareControllerDisconnect);
|
|
}
|
|
|
|
static fromContext(context: HostPluginContext): BaseHostPlugin {
|
|
const plugin = new this(context.plugin, context.host, context.logger);
|
|
return plugin;
|
|
}
|
|
|
|
detachHooks() {
|
|
this.host.hooks.detachAll(this.info.name);
|
|
}
|
|
|
|
/**
|
|
* Called immediately after the class is instantiated
|
|
*/
|
|
async init() {}
|
|
}
|