From 496ebd18a578182befd656d9f2174fdcf0536581 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Thu, 23 Feb 2023 20:15:49 +0100 Subject: [PATCH] Put instance runtime state into InstanceInfo class Use the data class pattern for storing the instance data on the controller. Improves documentation for plugins trying to use it. --- packages/controller/src/ControlConnection.js | 3 +- packages/controller/src/Controller.js | 5 ++- packages/controller/src/HostConnection.js | 3 +- packages/controller/src/InstanceInfo.js | 44 ++++++++++++++++++++ packages/lib/plugin.js | 9 ++-- 5 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 packages/controller/src/InstanceInfo.js diff --git a/packages/controller/src/ControlConnection.js b/packages/controller/src/ControlConnection.js index 7b9f865f..d1835205 100644 --- a/packages/controller/src/ControlConnection.js +++ b/packages/controller/src/ControlConnection.js @@ -16,6 +16,7 @@ const libPrometheus = require("@clusterio/lib/prometheus"); const libUsers = require("@clusterio/lib/users"); const BaseConnection = require("./BaseConnection"); +const InstanceInfo = require("./InstanceInfo"); const routes = require("./routes"); const strcmp = new Intl.Collator(undefined, { numerice: "true", sensitivity: "base" }).compare; @@ -261,7 +262,7 @@ class ControlConnection extends BaseConnection { }; instanceConfig.set("factorio.settings", settings); - let instance = { config: instanceConfig, status: "unassigned" }; + let instance = new InstanceInfo({ config: instanceConfig, status: "unassigned" }); this._controller.instances.set(instanceId, instance); await libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, null); this._controller.addInstanceHooks(instance); diff --git a/packages/controller/src/Controller.js b/packages/controller/src/Controller.js index 3f68a4d1..bc748b38 100644 --- a/packages/controller/src/Controller.js +++ b/packages/controller/src/Controller.js @@ -20,6 +20,7 @@ const libPrometheus = require("@clusterio/lib/prometheus"); const { logger } = require("@clusterio/lib/logging"); const HttpCloser = require("./HttpCloser"); +const InstanceInfo = require("./InstanceInfo"); const metrics = require("./metrics"); const routes = require("./routes"); const UserManager = require("./UserManager"); @@ -68,7 +69,7 @@ class Controller { /** * Mapping of instance id to instance info - * @type {Map} + * @type {Map} */ this.instances = null; @@ -379,7 +380,7 @@ class Controller { let instanceConfig = new libConfig.InstanceConfig("controller"); await instanceConfig.load(serializedConfig); let status = instanceConfig.get("instance.assigned_host") === null ? "unassigned" : "unknown"; - let instance = { config: instanceConfig, status }; + let instance = new InstanceInfo({ config: instanceConfig, status }); instances.set(instanceConfig.get("instance.id"), instance); } diff --git a/packages/controller/src/HostConnection.js b/packages/controller/src/HostConnection.js index 1f302b1c..7cccaee8 100644 --- a/packages/controller/src/HostConnection.js +++ b/packages/controller/src/HostConnection.js @@ -6,6 +6,7 @@ const libPlugin = require("@clusterio/lib/plugin"); const PlayerStats = require("@clusterio/lib/PlayerStats"); const BaseConnection = require("./BaseConnection"); +const InstanceInfo = require("./InstanceInfo"); /** @@ -160,7 +161,7 @@ class HostConnection extends BaseConnection { } instanceConfig.set("instance.assigned_host", this._id); - let newInstance = { config: instanceConfig, status: instanceData.status }; + let newInstance = new InstanceInfo({ config: instanceConfig, status: instanceData.status }); this._controller.instances.set(instanceConfig.get("instance.id"), newInstance); this._controller.addInstanceHooks(newInstance); await libLink.messages.assignInstance.send(this, { diff --git a/packages/controller/src/InstanceInfo.js b/packages/controller/src/InstanceInfo.js new file mode 100644 index 00000000..da71ce2a --- /dev/null +++ b/packages/controller/src/InstanceInfo.js @@ -0,0 +1,44 @@ +"use strict"; + +/** + * Runtime status of an instance on the controller + * @alias module:controller/src/InstanceInfo + */ +class InstanceInfo { + /** @type {module:lib/config.InstanceConfig} */ + config; + + /** + * Current status of the instance. One of: + * - `unknown`: Instance is assigned to a host but this host is currently + * not connected to the contreller. + * - `unassigned`: Instance is not assigned to a a host and exists only on + * the controller. + * - `stopped`: Instance is stopped. + * - `starting`: Instance is in the process of starting up. + * - `running`: Instance is running normally. + * - `stopping`: Instance is in the process of stopping. + * - `creating_save`: Instance is in the process of creating a save. + * - `exporting_data`: Instance is in the process of exporting game data. + * - `deleted`: Instance has been deleted. + * + * @type {string} + */ + status; + + // This is not actually json as a config can't be loaded synchronously but + // that is likely to change in the future. + constructor(json) { + this.config = json["config"]; + this.status = json["status"]; + } + + toJSON() { + return { + config: this.config.serialize(), + status: this.status, + }; + } +} + +module.exports = InstanceInfo; diff --git a/packages/lib/plugin.js b/packages/lib/plugin.js index 364c0c92..fe627a86 100644 --- a/packages/lib/plugin.js +++ b/packages/lib/plugin.js @@ -354,7 +354,8 @@ class BaseControllerPlugin { * the case of network outages if reconnect fails to re-establish the * session between the controller and the host. * - * @param {Object} instance - the instance that changed. + * @param {module:controller/src/InstanceInfo} instance - + * The instance that changed. * @param {?string} prev - the previous status of the instance. */ async onInstanceStatusChanged(instance, prev) { } @@ -378,7 +379,8 @@ class BaseControllerPlugin { * Invoked after the value of the config field given by `field` has * changed on an instance. * - * @param {Object} instance - The instance the config changed on. + * @param {module:controller/src/InstanceInfo} instance - + * The instance the config changed on. * @param {module:lib/config.ConfigGroup} group - * The group who's field got changed. * @param {string} field - Name of the field that changed. @@ -524,7 +526,8 @@ class BaseControllerPlugin { * Invoked when a player either joins or leaves an instance in the * cluster. * - * @param {Object} instance - the instance it occured on. + * @param {module:controller/src/InstanceInfo} instance - + * The instance it occured on. * @param {Object} event - Information about the event. * @param {string} event.type - Either "join", "leave" or "import". * @param {string} event.name - Name of the player that joined/left.