Controller: back to hosts, instances, modPacks, mods init to null

This commit is contained in:
Luciole committed 2023-08-14 11:26:48 +02:00
1 parent ef32f6f466
commit 25e65910dd
6 files changed
+67 -71

No files matched your search

+2 -2
View File
@@ -50,7 +50,7 @@ export default class BaseConnection extends lib.Link {
async handleModPackGetRequest(request: lib.ModPackGetRequest): Promise<lib.ModPack> {
let { id } = request;
let modPack = this._controller.modPacks.get(id);
let modPack = this._controller.modPacks!.get(id);
if (!modPack) {
throw new lib.RequestError(`Mod pack with ID ${id} does not exist`);
}
@@ -62,7 +62,7 @@ export default class BaseConnection extends lib.Link {
if (id === null) {
throw new lib.RequestError("Default mod pack not set on controller");
}
let modPack = this._controller.modPacks.get(id);
let modPack = this._controller.modPacks!.get(id);
if (!modPack) {
throw new lib.RequestError(`Default mod pack configured (${id}) does not exist`);
}
+13 -13
View File
@@ -206,7 +206,7 @@ export default class ControlConnection extends BaseConnection {
async handleHostListRequest(): Promise<lib.HostDetails[]> {
let list = [];
for (let host of this._controller.hosts.values()) {
for (let host of this._controller.hosts!.values()) {
list.push(new lib.HostDetails(
host.agent,
host.version,
@@ -275,7 +275,7 @@ export default class ControlConnection extends BaseConnection {
async handleInstanceDetailsListRequest() {
let list = [];
for (let instance of this._controller.instances.values()) {
for (let instance of this._controller.instances!.values()) {
list.push(new lib.InstanceDetails(
instance.config.get("instance.name"),
instance.id,
@@ -457,7 +457,7 @@ export default class ControlConnection extends BaseConnection {
}
async handleModPackListRequest() {
return [...this._controller.modPacks.values()];
return [...this._controller.modPacks!.values()];
}
async handleModPackSetSubscriptionsRequest(request: lib.ModPackSetSubscriptionsRequest) {
@@ -469,30 +469,30 @@ export default class ControlConnection extends BaseConnection {
if (modPack.id === undefined) {
throw new lib.RequestError(`Mod pack need an ID to be created`);
}
if (this._controller.modPacks.has(modPack.id)) {
if (this._controller.modPacks!.has(modPack.id)) {
throw new lib.RequestError(`Mod pack with ID ${modPack.id} already exist`);
}
this._controller.modPacks.set(modPack.id, modPack);
this._controller.modPacks!.set(modPack.id, modPack);
this._controller.modPackUpdated(modPack);
}
async handleModPackUpdateRequest(request: lib.ModPackUpdateRequest) {
let modPack = request.modPack;
if (modPack.id === undefined || !this._controller.modPacks.has(modPack.id)) {
if (modPack.id === undefined || !this._controller.modPacks!.has(modPack.id)) {
throw new lib.RequestError(`Mod pack with ID ${modPack.id} does not exist`);
}
this._controller.modPacks.set(modPack.id, modPack);
this._controller.modPacks!.set(modPack.id, modPack);
this._controller.modPackUpdated(modPack);
}
async handleModPackDeleteRequest(request: lib.ModPackDeleteRequest) {
let { id } = request;
let modPack = this._controller.modPacks.get(id);
let modPack = this._controller.modPacks!.get(id);
if (!modPack) {
throw new lib.RequestError(`Mod pack with ID ${id} does not exist`);
}
modPack.isDeleted = true;
this._controller.modPacks.delete(id);
this._controller.modPacks!.delete(id);
this._controller.modPackUpdated(modPack);
}
@@ -508,7 +508,7 @@ export default class ControlConnection extends BaseConnection {
async handleModGetRequest(request: lib.ModGetRequest) {
let { name, version } = request;
let filename = `${name}_${version}.zip`;
let mod = this._controller.mods.get(filename);
let mod = this._controller.mods!.get(filename);
if (!mod) {
throw new lib.RequestError(`Mod ${filename} does not exist`);
}
@@ -516,7 +516,7 @@ export default class ControlConnection extends BaseConnection {
}
async handleModListRequest() {
return [...this._controller.mods.values()];
return [...this._controller.mods!.values()];
}
static termsMatchesMod(terms: lib.ParsedTerm[], mod: lib.ModInfo) {
@@ -556,7 +556,7 @@ export default class ControlConnection extends BaseConnection {
type ModVersions = { name: string, versions: lib.ModInfo[] };
let results: Map<string, ModVersions> = new Map();
for (let mod of this._controller.mods.values()) {
for (let mod of this._controller.mods!.values()) {
if (
mod.factorioVersion !== factorioVersion
|| !ControlConnection.termsMatchesMod(query.terms, mod)
@@ -615,7 +615,7 @@ export default class ControlConnection extends BaseConnection {
async handleModDownloadRequest(request: lib.ModDownloadRequest) {
let { name, version } = request;
let filename = `${name}_${version}.zip`;
let mod = this._controller.mods.get(filename);
let mod = this._controller.mods!.get(filename);
if (!mod) {
throw new lib.RequestError(`Mod ${filename} does not exist`);
}
+41 -45
View File
@@ -52,13 +52,13 @@ export default class Controller {
app: Application;
/** Mapping of host id to host info */
hosts: Map<number, HostInfo> = new Map();
hosts: Map<number, HostInfo> | null = null;
/** Mapping of instance id to instance info */
instances: Map<number, InstanceInfo> = new Map();
instances: Map<number, InstanceInfo> | null = null;
/** Mapping of mod pack id to mod pack */
modPacks: Map<number, lib.ModPack> = new Map();
modPacks: Map<number, lib.ModPack> | null = null;
/** Mapping of mod names to mod infos */
mods: Map<string, lib.ModInfo> = new Map();
mods: Map<string, lib.ModInfo> | null = null;
/** User and roles manager for the cluster */
userManager: UserManager;
@@ -189,9 +189,9 @@ export default class Controller {
let databaseDirectory = this.config.get("controller.database_directory");
await fs.ensureDir(databaseDirectory);
await Controller.loadHosts(path.join(databaseDirectory, "hosts.json"), this.hosts);
await Controller.loadInstances(path.join(databaseDirectory, "instances.json"), this.instances);
await Controller.loadModPacks(path.join(databaseDirectory, "mod-packs.json"), this.modPacks);
this.hosts = await Controller.loadHosts(path.join(databaseDirectory, "hosts.json"));
this.instances = await Controller.loadInstances(path.join(databaseDirectory, "instances.json"));
this.modPacks = await Controller.loadModPacks(path.join(databaseDirectory, "mod-packs.json"));
await this.userManager.load(path.join(databaseDirectory, "users.json"));
let modsDirectory = this.config.get("controller.mods_directory");
@@ -201,7 +201,7 @@ export default class Controller {
this.config.on("fieldChanged", (group, field, prev) => {
lib.invokeHook(this.plugins, "onControllerConfigFieldChanged", group, field, prev);
});
for (let instance of this.instances.values()) {
for (let instance of this.instances!.values()) {
this.addInstanceHooks(instance);
}
@@ -315,15 +315,15 @@ export default class Controller {
}
let databaseDirectory = this.config.get("controller.database_directory");
if (this.hosts.size > 0) {
if (this.hosts) {
await Controller.saveHosts(path.join(databaseDirectory, "hosts.json"), this.hosts);
}
if (this.instances.size > 0) {
if (this.instances) {
await Controller.saveInstances(path.join(databaseDirectory, "instances.json"), this.instances);
}
if (this.modPacks.size > 0) {
if (this.modPacks) {
await Controller.saveModPacks(path.join(databaseDirectory, "mod-packs.json"), this.modPacks);
}
@@ -350,36 +350,36 @@ export default class Controller {
logger.info("Goodbye");
}
static async loadHosts(filePath: string, hosts:Map<number, any>) {
hosts.clear();
static async loadHosts(filePath: string): Promise<Map<number, HostInfo>> {
let serialized: [number, HostInfo][];
try {
const serialized = JSON.parse(await fs.readFile(filePath, { encoding: 'utf8' }));
// TODO: Remove after release.
if (serialized.length && !(serialized[0] instanceof Array)) {
for (let [id, host] of serialized) {
hosts.set(id ,host)
}
}
serialized = JSON.parse(await fs.readFile(filePath, { encoding: 'utf8' }));
} catch (err: any) {
if (err.code !== "ENOENT") {
throw err;
}
hosts.clear();
return new Map();
}
// TODO: Remove after release.
if (serialized.length && !(serialized[0] instanceof Array)) {
return new Map(); // Discard old format.
}
return new Map(serialized);
}
static async saveHosts(filePath: string, hosts: Map<number, HostInfo>) {
await lib.safeOutputFile(filePath, JSON.stringify([...hosts.entries()], null, 4));
}
static async loadInstances(filePath: string, instances: Map<number, InstanceInfo>) {
static async loadInstances(filePath: string): Promise<Map<number, InstanceInfo>> {
logger.info(`Loading ${filePath}`);
instances.clear();
let instances = new Map();
try {
const serialized = JSON.parse(await fs.readFile(filePath, { encoding: 'utf8' }));
let serialized = JSON.parse(await fs.readFile(filePath, { encoding: "utf8" }));
for (let serializedConfig of serialized) {
let instanceConfig = new lib.InstanceConfig("controller");
await instanceConfig.load(serializedConfig);
@@ -395,7 +395,10 @@ export default class Controller {
if (err.code !== "ENOENT") {
throw err;
}
return new Map();
}
return instances;
}
static async saveInstances(filePath: string, instances: Map<number, InstanceInfo>) {
@@ -407,31 +410,24 @@ export default class Controller {
await lib.safeOutputFile(filePath, JSON.stringify(serialized, null, 4));
}
static async loadModPacks(filePath: string, modPacks: Map<number, lib.ModPack>) {
modPacks.clear();
static async loadModPacks(filePath: string): Promise<Map<number, lib.ModPack>> {
let json;
try {
const json = JSON.parse(await fs.readFile(filePath, { encoding: 'utf8' }));
for (const modPackJson of json) {
modPacks.set(
modPackJson.id,
lib.ModPack.fromJSON(modPackJson)
)
}
json = JSON.parse(await fs.readFile(filePath, { encoding : "utf8" }));
} catch (err: any) {
if (err.code !== "ENOENT") {
throw err;
}
return new Map();
}
return new Map(json.map((e: any) => [e.id, lib.ModPack.fromJSON(e)]));
}
static async saveModPacks(filePath: string, modPacks: Map<number, lib.ModPack>) {
await lib.safeOutputFile(filePath, JSON.stringify([...modPacks.values()], null, 4));
}
static async loadModInfos(modsDirectory: string) {
static async loadModInfos(modsDirectory: string): Promise<Map<string,lib.ModInfo>> {
let mods = new Map();
for (let entry of await fs.readdir(modsDirectory, { withFileTypes: true })) {
if (entry.isDirectory()) {
@@ -479,14 +475,14 @@ export default class Controller {
async deleteMod(name: string, version: string): Promise<void> {
let filename = `${name}_${version}.zip`;
let mod = this.mods.get(filename);
let mod = this.mods!.get(filename);
if (!mod) {
throw new Error(`Mod ${filename} does not exist`);
}
let modsDirectory = this.config.get("controller.mods_directory");
await fs.unlink(path.join(modsDirectory, filename));
this.mods.delete(filename);
this.mods!.delete(filename);
mod.isDeleted = true;
this.modUpdated(mod);
}
@@ -595,7 +591,7 @@ export default class Controller {
* @throws {module:lib.RequestError} if the instance does not exist.
*/
getRequestInstance(instanceId:number):InstanceInfo {
let instance = this.instances.get(instanceId);
let instance = this.instances!.get(instanceId);
if (!instance) {
throw new lib.RequestError(`Instance with ID ${instanceId} does not exist`);
}
@@ -621,7 +617,7 @@ export default class Controller {
*/
async instanceCreate(instanceConfig: lib.InstanceConfig): Promise<InstanceInfo> {
let instanceId = instanceConfig.get("instance.id");
if (this.instances.has(instanceId)) {
if (this.instances!.has(instanceId)) {
throw new lib.RequestError(`Instance with ID ${instanceId} already exists`);
}
@@ -652,7 +648,7 @@ export default class Controller {
instanceConfig.set("factorio.settings", settings);
let instance = new InstanceInfo({ config: instanceConfig, status: "unassigned" });
this.instances.set(instanceId, instance);
this.instances!.set(instanceId, instance);
await lib.invokeHook(this.plugins, "onInstanceStatusChanged", instance, null);
this.addInstanceHooks(instance);
return instance;
@@ -723,7 +719,7 @@ export default class Controller {
if (hostId !== null) {
await this.sendTo({ hostId }, new lib.InstanceDeleteInternalRequest(instanceId));
}
this.instances.delete(instanceId);
this.instances!.delete(instanceId);
let prev = instance.status;
instance.status = "deleted";
@@ -1097,7 +1093,7 @@ export default class Controller {
connection = this.wsServer.controlConnections.get(dst.id);
} else if (dst.type === lib.Address.instance) {
let instance = this.instances.get(dst.id);
let instance = this.instances!.get(dst.id);
if (!instance) {
return;
}
+1 -1
View File
@@ -40,7 +40,7 @@ export default class ControllerRouter {
msg = `Host ${dst.id} is offline`;
}
} else if (dst.type === lib.Address.instance) {
let instance = this.controller.instances.get(dst.id);
let instance = this.controller.instances!.get(dst.id);
if (!instance) {
msg = `Instance ${dst.id} does not exist`;
} else {
+8 -8
View File
@@ -45,7 +45,7 @@ export default class HostConnection extends BaseConnection {
this.plugins = new Map(Object.entries(registerData.plugins));
this._checkPluginVersions();
this._controller.hosts.set(this._id, {
this._controller.hosts!.set(this._id, {
agent: this._agent,
id: this._id,
name: this._name,
@@ -65,7 +65,7 @@ export default class HostConnection extends BaseConnection {
this.connector.on("close", () => {
// Update status to unknown for instances on this host.
for (let instance of this._controller.instances.values()) {
for (let instance of this._controller.instances!.values()) {
if (instance.config.get("instance.assigned_host") !== this._id) {
continue;
}
@@ -100,7 +100,7 @@ export default class HostConnection extends BaseConnection {
break;
case lib.Address.instance:
let instance = this._controller.instances.get(message.src.id);
let instance = this._controller.instances!.get(message.src.id);
if (!instance || instance.config.get("instance.assigned_host") !== this._id) {
throw new lib.InvalidMessage(
`Received message with invalid src ${message.src} from ${origin}`
@@ -152,7 +152,7 @@ export default class HostConnection extends BaseConnection {
}
async handleInstanceStatusChangedEvent(request: lib.InstanceStatusChangedEvent) {
let instance = this._controller.instances.get(request.instanceId);
let instance = this._controller.instances!.get(request.instanceId);
// It's possible to get updates from an instance that does not exist
// or is not assigned to the host it originated from if it was
@@ -182,7 +182,7 @@ export default class HostConnection extends BaseConnection {
async handleInstancesUpdateRequest(request: lib.InstancesUpdateRequest) {
// Push updated instance configs
for (let instance of this._controller.instances.values()) {
for (let instance of this._controller.instances!.values()) {
if (instance.config.get("instance.assigned_host") === this._id) {
await this.send(
new lib.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host"))
@@ -195,7 +195,7 @@ export default class HostConnection extends BaseConnection {
let instanceConfig = new lib.InstanceConfig("controller");
await instanceConfig.load(instanceData.config as lib.SerializedConfig, "host");
let controllerInstance = this._controller.instances.get(instanceConfig.get("instance.id"));
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) {
@@ -220,7 +220,7 @@ export default class HostConnection extends BaseConnection {
instanceConfig.set("instance.assigned_host", this._id);
let newInstance = new InstanceInfo({ config: instanceConfig, status: instanceData.status as InstanceStatus });
this._controller.instances.set(instanceConfig.get("instance.id"), newInstance);
this._controller.instances!.set(instanceConfig.get("instance.id"), newInstance);
this._controller.addInstanceHooks(newInstance);
await this.send(
new lib.InstanceAssignInternalRequest(
@@ -283,7 +283,7 @@ export default class HostConnection extends BaseConnection {
user.recalculatePlayerStats();
this._controller.userUpdated(user);
let instance = this._controller.instances.get(instanceId);
let instance = this._controller.instances!.get(instanceId);
await lib.invokeHook(this._controller.plugins, "onPlayerEvent", instance, {
type: event.type,
name: event.name,
+2 -2
View File
@@ -273,13 +273,13 @@ ${err.stack}`
connector.on("close", () => {
if (this.hostConnections.get(data.id) === connection) {
this.hostConnections.delete(data.id);
this.controller.hostUpdated(this.controller.hosts.get(data.id) as HostInfo);
this.controller.hostUpdated(this.controller.hosts!.get(data.id) as HostInfo);
} else {
logger.warn("Unlisted HostConnection closed");
}
});
this.hostConnections.set(data.id, connection);
this.controller.hostUpdated(this.controller.hosts.get(data.id) as HostInfo);
this.controller.hostUpdated(this.controller.hosts!.get(data.id) as HostInfo);
let src = new lib.Address(lib.Address.host, data.id);
connector.ready(socket, src, sessionToken, undefined);
}