From 688ddc529b69a235fd03514e431794a443782276 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Mon, 15 Jan 2024 22:19:38 +0100 Subject: [PATCH] Separate connection related data from host data Split out host specific data from RegisterHostData that is not related to the establishment of a connection to the controller into it's own HostInfoUpdate event. This allows this data to be updated when the config values they are taken from are changed. --- docs/devs/protocol.md | 2 - packages/controller/src/HostConnection.ts | 68 ++++++++++++----------- packages/controller/src/WsServer.ts | 4 +- packages/host/host.ts | 2 - packages/host/src/Host.ts | 15 +++++ packages/lib/src/data/messages_core.ts | 6 +- packages/lib/src/data/messages_host.ts | 38 +++++++++++++ packages/lib/src/link/messages.ts | 1 + 8 files changed, 94 insertions(+), 42 deletions(-) diff --git a/docs/devs/protocol.md b/docs/devs/protocol.md index 46d72949..ea28005c 100644 --- a/docs/devs/protocol.md +++ b/docs/devs/protocol.md @@ -108,7 +108,6 @@ Host handshake for establishing a new connection session. - `token: string` - Authentication token. - `version: string` - The protocol version of the host, e.g. "2.0.0". -- `name: string` - Name of the host. - `id: integer` - ID of the host. - `plugins: Object` - Object mapping plugin names to plugin version for plugins that are available on the host. @@ -242,7 +241,6 @@ Host registering a new connection session. "data": { "token": "xyzabc123", "version": "2.0.0", - "name": "Foo", "id": 123 } } diff --git a/packages/controller/src/HostConnection.ts b/packages/controller/src/HostConnection.ts index 62f4546e..7c2bdc4c 100644 --- a/packages/controller/src/HostConnection.ts +++ b/packages/controller/src/HostConnection.ts @@ -16,9 +16,7 @@ import HostInfo from "./HostInfo"; * @alias module:controller/src/HostConnection */ export default class HostConnection extends BaseConnection { - private _id: number; - private _name: string; - private _version: string; + private info: HostInfo; plugins: Map; constructor( @@ -28,26 +26,24 @@ export default class HostConnection extends BaseConnection { ) { super(connector, controller); - this._id = registerData.id; - this._name = registerData.name; - this._version = registerData.version; this.plugins = new Map(Object.entries(registerData.plugins)); - this._checkPluginVersions(); - const previousHostInfo = this._controller.hosts.get(this._id); - const currentHostInfo = new HostInfo( - this._id, - this._name, - this._version, + const previousHostInfo = this._controller.hosts.get(registerData.id); + this.info = new HostInfo( + registerData.id, + previousHostInfo?.name ?? "", + registerData.version, this.plugins, true, - registerData.publicAddress ?? "", + previousHostInfo?.publicAddress, previousHostInfo?.tokenValidAfter, - Date.now(), + 0, false, ); - this._controller.hosts.set(this._id, currentHostInfo); - this._controller.hostsUpdated([currentHostInfo]); + this._controller.hosts.set(this.id, this.info); + this._controller.hostsUpdated([this.info]); + + this._checkPluginVersions(); for (let event of ["connect", "drop", "resume", "close"] as const) { // eslint-disable-next-line no-loop-func @@ -62,7 +58,7 @@ export default class HostConnection extends BaseConnection { // Update status to unknown for instances on this host. const instances: InstanceInfo[] = []; for (let instance of this._controller.instances.values()) { - if (instance.config.get("instance.assigned_host") !== this._id) { + if (instance.config.get("instance.assigned_host") !== this.id) { continue; } @@ -73,10 +69,11 @@ export default class HostConnection extends BaseConnection { } this._controller.instanceDetailsUpdated(instances); - currentHostInfo.connected = false; - this._controller.hostsUpdated([currentHostInfo]); + this.info.connected = false; + this._controller.hostsUpdated([this.info]); }); + this.handle(lib.HostInfoUpdateEvent, this.handleHostInfoUpdateEvent.bind(this)); this.handle(lib.InstanceStatusChangedEvent, this.handleInstanceStatusChangedEvent.bind(this)); this.handle(lib.InstancesUpdateRequest, this.handleInstancesUpdateRequest.bind(this)); this.handle(lib.InstanceSaveDetailsUpdatesEvent, this.handleInstanceSaveDetailsUpdatesEvent.bind(this)); @@ -101,7 +98,7 @@ export default class HostConnection extends BaseConnection { case lib.Address.instance: let instance = this._controller.instances.get(message.src.id); - if (!instance || instance.config.get("instance.assigned_host") !== this._id) { + if (!instance || instance.config.get("instance.assigned_host") !== this.id) { throw new lib.InvalidMessage( `Received message with invalid src ${message.src} from ${origin}` ); @@ -118,21 +115,24 @@ export default class HostConnection extends BaseConnection { for (let [name, version] of this.plugins) { let info = pluginInfos.get(name); if (!info) { - logger.warn(`Host ${this._name} has plugin ${name} ${version} which the controller does not have`); + logger.warn( + `Host ${this.info.name} (${this.id}) has plugin ${name} ${version} which the ` + + "controller does not have", + ); continue; } if (info.version !== version) { logger.warn( - `Host ${this._name} has plugin ${name} ${version} which does not match the version of this ` + - `plugin on the controller (${info.version})` + `Host ${this.info.name} (${this.id}) has plugin ${name} ${version} which does not match ` + + `the version of this plugin on the controller (${info.version})` ); } } for (let [name, info] of pluginInfos) { if (!this.plugins.has(name)) { - logger.warn(`Host ${this._name} is missing plugin ${name} ${info.version}`); + logger.warn(`Host ${this.info.name} (${this.id}) is missing plugin ${name} ${info.version}`); } } } @@ -148,7 +148,13 @@ export default class HostConnection extends BaseConnection { * @returns {number} host ID. */ get id() { - return this._id; + return this.info.id; + } + + async handleHostInfoUpdateEvent(event: lib.HostInfoUpdateEvent) { + this.info.name = event.update.name; + this.info.publicAddress = event.update.publicAddress; + this._controller.hostsUpdated([this.info]); } async handleInstanceStatusChangedEvent(request: lib.InstanceStatusChangedEvent) { @@ -158,7 +164,7 @@ export default class HostConnection extends BaseConnection { // or is not assigned to the host it originated from if it was // reassigned or deleted while the connection to the host it was // originally on was down at the time. - if (!instance || instance.config.get("instance.assigned_host") !== this._id) { + if (!instance || instance.config.get("instance.assigned_host") !== this.id) { logger.warn(`Got bogus update for instance id ${request.instanceId}`); return; } @@ -184,7 +190,7 @@ export default class HostConnection extends BaseConnection { async handleInstancesUpdateRequest(request: lib.InstancesUpdateRequest) { // Push updated instance configs for (let instance of this._controller.instances.values()) { - if (instance.config.get("instance.assigned_host") === this._id) { + if (instance.config.get("instance.assigned_host") === this.id) { await this.send( new lib.InstanceAssignInternalRequest(instance.id, instance.config.toRemote("host")) ); @@ -200,7 +206,7 @@ export default class HostConnection extends BaseConnection { let controllerInstance = this._controller.instances.get(instanceConfig.get("instance.id")); if (controllerInstance) { // Check if this instance is assigned somewhere else. - if (controllerInstance.config.get("instance.assigned_host") !== this._id) { + if (controllerInstance.config.get("instance.assigned_host") !== this.id) { await this.send( new lib.InstanceUnassignInternalRequest(instanceConfig.get("instance.id")) ); @@ -222,7 +228,7 @@ export default class HostConnection extends BaseConnection { continue; } - instanceConfig.set("instance.assigned_host", this._id); + instanceConfig.set("instance.assigned_host", this.id); let newInstance = new InstanceInfo( instanceConfig, instanceData.status, @@ -298,8 +304,8 @@ export default class HostConnection extends BaseConnection { async handleLogMessageEvent(event: lib.LogMessageEvent) { this._controller.clusterLogger.log({ ...event.info, - host_id: this._id, - host_name: this._name, + host_id: this.id, + host_name: this.info.name, }); } diff --git a/packages/controller/src/WsServer.ts b/packages/controller/src/WsServer.ts index d2166cfa..3fc0d988 100644 --- a/packages/controller/src/WsServer.ts +++ b/packages/controller/src/WsServer.ts @@ -261,11 +261,11 @@ ${err.stack}` } logger.info( - `WsServer | registered host ${data.name} (${data.id}) using version ${data.version}` + `WsServer | registered host ${data.id} using version ${data.version}` ); if (data.version !== packageVersion) { logger.warn( - `Host ${data.name} (${data.id}) connected using version ${data.version} which does not match the ` + + `Host ${data.id} connected using version ${data.version} which does not match the ` + `version of the controller is currently running (${packageVersion}). It may not work as expected.` ); } diff --git a/packages/host/host.ts b/packages/host/host.ts index bce5e8a2..2026ebe4 100755 --- a/packages/host/host.ts +++ b/packages/host/host.ts @@ -52,9 +52,7 @@ export class HostConnector extends lib.WebSocketClientConnector { new lib.RegisterHostData( this.hostConfig.get("host.controller_token"), version, - this.hostConfig.get("host.name"), this.hostConfig.get("host.id"), - this.hostConfig.get("host.public_address"), plugins, ) ) diff --git a/packages/host/src/Host.ts b/packages/host/src/Host.ts index 971f82f3..a274f6a6 100644 --- a/packages/host/src/Host.ts +++ b/packages/host/src/Host.ts @@ -288,6 +288,9 @@ export default class Host extends lib.Link { this.config = hostConfig; this.config.on("fieldChanged", (name, curr, prev) => { + if (name === "host.name" || name === "host.public_address") { + this.sendHostUpdate(); + } lib.invokeHook(this.plugins, "onHostConfigFieldChanged", name, curr, prev); }); @@ -301,6 +304,7 @@ export default class Host extends lib.Link { return; } + this.sendHostUpdate(); this.updateInstances().catch((err) => { if (err instanceof lib.SessionLost) { return undefined; @@ -992,6 +996,17 @@ export default class Host extends lib.Link { await fs.remove(instanceInfo.path); } + sendHostUpdate() { + this.send( + new lib.HostInfoUpdateEvent( + new lib.HostInfoUpdate( + this.config.get("host.name"), + this.config.get("host.public_address"), + ), + ), + ); + } + /** * Discover available instances * diff --git a/packages/lib/src/data/messages_core.ts b/packages/lib/src/data/messages_core.ts index ba531930..4a84e9c4 100644 --- a/packages/lib/src/data/messages_core.ts +++ b/packages/lib/src/data/messages_core.ts @@ -212,23 +212,19 @@ export class RegisterHostData { constructor( public token: string, public version: string, - public name: string, public id: number, - public publicAddress: string | undefined, public plugins: Record, ) { } static jsonSchema = Type.Object({ "token": Type.String(), "version": Type.String(), - "name": Type.String(), "id": Type.Integer(), - "publicAddress": Type.Optional(Type.String()), "plugins": Type.Record(Type.String(), Type.String()), }); static fromJSON(json: Static) { - return new this(json.token, json.version, json.name, json.id, json.publicAddress, json.plugins); + return new this(json.token, json.version, json.id, json.plugins); } } diff --git a/packages/lib/src/data/messages_host.ts b/packages/lib/src/data/messages_host.ts index 4566c3f0..5f2cf88a 100644 --- a/packages/lib/src/data/messages_host.ts +++ b/packages/lib/src/data/messages_host.ts @@ -105,6 +105,44 @@ export class HostListRequest { static Response = jsonArray(HostDetails); } +export class HostInfoUpdate { + constructor( + public name: string, + public publicAddress: string, + ) { } + + static jsonSchema = Type.Object({ + "name": Type.String(), + "publicAddress": Type.String(), + }); + + static fromJSON(json: Static) { + return new this( + json.name, + json.publicAddress, + ); + } +} + +export class HostInfoUpdateEvent { + declare ["constructor"]: typeof HostInfoUpdateEvent; + static type = "event" as const; + static src = "host" as const; + static dst = "controller" as const; + + constructor( + public update: HostInfoUpdate, + ) { } + + static jsonSchema = Type.Object({ + "update": HostInfoUpdate.jsonSchema, + }); + + static fromJSON(json: Static) { + return new this(HostInfoUpdate.fromJSON(json.update)); + } +} + export class HostUpdatesEvent { declare ["constructor"]: typeof HostUpdatesEvent; static type = "event" as const; diff --git a/packages/lib/src/link/messages.ts b/packages/lib/src/link/messages.ts index 6f4494aa..560a5da6 100644 --- a/packages/lib/src/link/messages.ts +++ b/packages/lib/src/link/messages.ts @@ -36,6 +36,7 @@ export const dataClasses: (RequestClass | EventClass) host.HostConfigSetFieldRequest, host.HostConfigSetPropRequest, host.HostListRequest, + host.HostInfoUpdateEvent, host.HostUpdatesEvent, host.HostMetricsRequest, host.ControllerConnectionEvent,