Browse Source

refactor: Handle dependencies when stopping modules

Owen Diffey 1 năm trước cách đây
mục cha
commit
1ec9960709

+ 0 - 1
backend/src/BaseModule.ts

@@ -97,7 +97,6 @@ export default abstract class BaseModule {
 	public async shutdown() {
 		this.log(`Module (${this.name}) stopping`);
 		this.setStatus(ModuleStatus.STOPPING);
-		await this.stopped();
 	}
 
 	/**

+ 32 - 12
backend/src/ModuleManager.ts

@@ -120,19 +120,39 @@ export default class ModuleManager {
 	 * shutdown - Handle shutdown
 	 */
 	public async shutdown() {
-		if (this.modules)
-			await Promise.all(
-				Object.values(this.modules).map(async module => {
-					if (
-						[
-							ModuleStatus.STARTED,
-							ModuleStatus.STARTING,
-							ModuleStatus.ERROR
-						].includes(module.getStatus())
-					)
-						await module.shutdown();
-				})
+		if (this.modules) {
+			const modules = Object.entries(this.modules).filter(([, module]) =>
+				[
+					ModuleStatus.STARTED,
+					ModuleStatus.STARTING,
+					ModuleStatus.ERROR
+				].includes(module.getStatus())
 			);
+
+			const shutdownOrder: (keyof Modules)[] = [];
+
+			for (const [name, module] of modules) {
+				if (!shutdownOrder.includes(name)) shutdownOrder.push(name);
+
+				const dependencies = module.getDependentModules();
+
+				dependencies
+					.filter(dependency => shutdownOrder.includes(dependency))
+					.forEach(dependency => {
+						shutdownOrder.splice(
+							shutdownOrder.indexOf(dependency),
+							1
+						);
+					});
+
+				shutdownOrder.push(...dependencies);
+			}
+
+			for (const moduleName of shutdownOrder) {
+				// eslint-disable-next-line no-await-in-loop
+				await this.getModule(moduleName)?.shutdown();
+			}
+		}
 	}
 
 	static getPrimaryInstance(): ModuleManager {

+ 2 - 0
backend/src/modules/APIModule.ts

@@ -33,6 +33,8 @@ export default class APIModule extends BaseModule {
 	 */
 	public override async shutdown() {
 		await super.shutdown();
+
+		await super.stopped();
 	}
 
 	/**

+ 1 - 0
backend/src/modules/DataModule.ts

@@ -84,6 +84,7 @@ export default class DataModule extends BaseModule {
 		//		if (this.redisClient) await this.redisClient.quit();
 		patchEventEmitter.removeAllListeners();
 		if (this.mongoConnection) await this.mongoConnection.close();
+		await this.stopped();
 	}
 
 	/**

+ 2 - 0
backend/src/modules/EventsModule.ts

@@ -290,6 +290,8 @@ export default class EventsModule extends BaseModule {
 
 		this.subscriptions = {};
 		this.scheduleCallbacks = {};
+
+		await this.stopped();
 	}
 }
 

+ 8 - 0
backend/src/modules/StationModule.ts

@@ -21,6 +21,14 @@ export default class StationModule extends BaseModule {
 		await super.started();
 	}
 
+	/**
+	 * shutdown - Shutdown station module
+	 */
+	public override async shutdown() {
+		await super.shutdown();
+		await super.stopped();
+	}
+
 	/**
 	 * addToQueue - Add media to queue
 	 *

+ 2 - 0
backend/src/modules/WebSocketModule.ts

@@ -198,6 +198,8 @@ export default class WebSocketModule extends BaseModule {
 
 		if (this.httpServer) this.httpServer.close();
 		if (this.wsServer) this.wsServer.close();
+
+		await this.stopped();
 	}
 }