Sfoglia il codice sorgente

feat: Add module job api access config and virtual jobs

Owen Diffey 1 anno fa
parent
commit
b70bb753db
2 ha cambiato i file con 87 aggiunte e 8 eliminazioni
  1. 86 0
      backend/src/BaseModule.ts
  2. 1 8
      backend/src/Job.ts

+ 86 - 0
backend/src/BaseModule.ts

@@ -1,3 +1,4 @@
+import JobContext from "./JobContext";
 import JobQueue from "./JobQueue";
 import LogBook, { Log } from "./LogBook";
 import ModuleManager from "./ModuleManager";
@@ -26,6 +27,25 @@ export default abstract class BaseModule {
 
 	protected dependentModules: (keyof Modules)[];
 
+	protected jobApiDefault: boolean;
+
+	protected jobConfig: Record<
+		string,
+		| boolean
+		| {
+				api?: boolean;
+				method?: (context: JobContext, payload?: any) => Promise<any>;
+		  }
+	>;
+
+	protected jobs: Record<
+		string,
+		{
+			api: boolean;
+			method: (context: JobContext, payload?: any) => Promise<any>;
+		}
+	>;
+
 	/**
 	 * Base Module
 	 *
@@ -38,6 +58,9 @@ export default abstract class BaseModule {
 		this.name = name;
 		this.status = ModuleStatus.LOADED;
 		this.dependentModules = [];
+		this.jobApiDefault = true;
+		this.jobConfig = {};
+		this.jobs = {};
 		this.log(`Module (${this.name}) loaded`);
 	}
 
@@ -75,6 +98,68 @@ export default abstract class BaseModule {
 		return this.dependentModules;
 	}
 
+	/**
+	 * loadJobs - Load jobs available via api module
+	 */
+	private async loadJobs() {
+		this.jobs = {};
+
+		const module = Object.getPrototypeOf(this);
+		await Promise.all(
+			Object.getOwnPropertyNames(module).map(async property => {
+				if (
+					typeof module[property] !== "function" ||
+					Object.prototype.hasOwnProperty.call(
+						BaseModule.prototype,
+						property
+					)
+				)
+					return;
+
+				const options = this.jobConfig[property];
+
+				let api = this.jobApiDefault;
+				if (
+					typeof options === "object" &&
+					typeof options.api === "boolean"
+				)
+					api = options.api;
+				else if (typeof options === "boolean") api = options;
+
+				this.jobs[property] = {
+					api,
+					method: module[property]
+				};
+			})
+		);
+
+		await Promise.all(
+			Object.entries(this.jobConfig).map(async ([name, options]) => {
+				if (
+					typeof options === "object" &&
+					typeof options.method === "function"
+				) {
+					if (this.jobs[name])
+						throw new Error(`Job "${name}" is already defined`);
+
+					this.jobs[name] = {
+						api: options.api ?? this.jobApiDefault,
+						method: options.method
+					};
+				}
+			})
+		);
+	}
+
+	/**
+	 * getJob - Get module job
+	 */
+	public getJob(name: string) {
+		if (!this.jobs[name]) throw new Error(`Job "${name}" not found.`);
+
+		return this.jobs[name];
+	}
+
 	/**
 	 * startup - Startup module
 	 */
@@ -87,6 +172,7 @@ export default abstract class BaseModule {
 	 * started - called with the module has started
 	 */
 	protected async started() {
+		await this.loadJobs();
 		this.log(`Module (${this.name}) started`);
 		this.setStatus(ModuleStatus.STARTED);
 	}

+ 1 - 8
backend/src/Job.ts

@@ -70,14 +70,7 @@ export default class Job {
 		if (!module) throw new Error("Module not found.");
 		this.module = module;
 
-		// eslint-disable-next-line
-		// @ts-ignore
-		const jobFunction = this.module[this.name];
-		if (!jobFunction || typeof jobFunction !== "function")
-			throw new Error("Job not found.");
-		if (Object.prototype.hasOwnProperty.call(BaseModule, this.name))
-			throw new Error("Illegal job function.");
-		this.jobFunction = jobFunction;
+		this.jobFunction = this.module.getJob(this.name).method;
 
 		this.payload = payload;