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.
This commit is contained in:
Hornwitser committed 2024-01-15 22:19:38 +01:00
1 parent 790f880e98
commit 688ddc529b
8 files changed
+94 -42

No files matched your search

-2
View File
@@ -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<string, string>` -
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
}
}
+37 -31
View File
@@ -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<string, string>;
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,
});
}
+2 -2
View File
@@ -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.`
);
}
-2
View File
@@ -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,
)
)
+15
View File
@@ -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
*
+1 -5
View File
@@ -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<string, string>,
) { }
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<typeof this.jsonSchema>) {
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);
}
}
+38
View File
@@ -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<typeof this.jsonSchema>) {
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<typeof this.jsonSchema>) {
return new this(HostInfoUpdate.fromJSON(json.update));
}
}
export class HostUpdatesEvent {
declare ["constructor"]: typeof HostUpdatesEvent;
static type = "event" as const;
+1
View File
@@ -36,6 +36,7 @@ export const dataClasses: (RequestClass<unknown, unknown> | EventClass<unknown>)
host.HostConfigSetFieldRequest,
host.HostConfigSetPropRequest,
host.HostListRequest,
host.HostInfoUpdateEvent,
host.HostUpdatesEvent,
host.HostMetricsRequest,
host.ControllerConnectionEvent,