From d21f99e6096b89fb5d296942089f64a7da006ce9 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 7 Jun 2021 08:08:39 -0400 Subject: [PATCH] Await `onActivate`/`onDeactive` of extensions (#2963) Signed-off-by: Sebastian Malton --- src/extensions/extension-loader.ts | 7 ++- src/extensions/lens-extension.ts | 73 ++++++++++++------------------ 2 files changed, 32 insertions(+), 48 deletions(-) diff --git a/src/extensions/extension-loader.ts b/src/extensions/extension-loader.ts index 6a4af088e8..da2669550f 100644 --- a/src/extensions/extension-loader.ts +++ b/src/extensions/extension-loader.ts @@ -26,7 +26,7 @@ import { action, computed, makeObservable, observable, reaction, when } from "mo import path from "path"; import { getHostedCluster } from "../common/cluster-store"; import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc"; -import { Singleton, toJS } from "../common/utils"; +import { Disposer, Singleton, toJS } from "../common/utils"; import logger from "../main/logger"; import type { InstalledExtension } from "./extension-discovery"; import { ExtensionsStore } from "./extensions-store"; @@ -296,7 +296,7 @@ export class ExtensionLoader extends Singleton { }); } - protected autoInitExtensions(register: (ext: LensExtension) => Promise) { + protected autoInitExtensions(register: (ext: LensExtension) => Promise) { return reaction(() => this.toJSON(), installedExtensions => { for (const [extId, extension] of installedExtensions) { const alreadyInit = this.instances.has(extId); @@ -311,8 +311,7 @@ export class ExtensionLoader extends Singleton { const instance = new LensExtensionClass(extension); - instance.whenEnabled(() => register(instance)); - instance.enable(); + instance.enable(register); this.instances.set(extId, instance); } catch (err) { logger.error(`${logModule}: activation extension error`, { ext: extension, err }); diff --git a/src/extensions/lens-extension.ts b/src/extensions/lens-extension.ts index 6f03829121..f3910308fd 100644 --- a/src/extensions/lens-extension.ts +++ b/src/extensions/lens-extension.ts @@ -20,11 +20,11 @@ */ import type { InstalledExtension } from "./extension-discovery"; -import { action, observable, reaction, makeObservable } from "mobx"; +import { action, observable, makeObservable } from "mobx"; import { FilesystemProvisionerStore } from "../main/extension-filesystem"; import logger from "../main/logger"; import type { ProtocolHandlerRegistration } from "./registries"; -import { disposer } from "../common/utils"; +import { Disposer, disposer } from "../common/utils"; export type LensExtensionId = string; // path to manifest (package.json) export type LensExtensionConstructor = new (...args: ConstructorParameters) => LensExtension; @@ -83,59 +83,44 @@ export class LensExtension { } @action - async enable() { - if (this.isEnabled) return; - this.isEnabled = true; - this.onActivate?.(); - logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); + async enable(register: (ext: LensExtension) => Promise) { + if (this.isEnabled) { + return; + } + + try { + await this.onActivate(); + this.isEnabled = true; + + this[Disposers].push(...await register(this)); + logger.info(`[EXTENSION]: enabled ${this.name}@${this.version}`); + } catch (error) { + logger.error(`[EXTENSION]: failed to activate ${this.name}@${this.version}: ${error}`); + } } @action async disable() { - if (!this.isEnabled) return; - this.isEnabled = false; - this.onDeactivate?.(); - this[Disposers](); - logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); - } + if (!this.isEnabled) { + return; + } - toggle(enable?: boolean) { - if (typeof enable === "boolean") { - enable ? this.enable() : this.disable(); - } else { - this.isEnabled ? this.disable() : this.enable(); + this.isEnabled = false; + + try { + await this.onDeactivate(); + this[Disposers](); + logger.info(`[EXTENSION]: disabled ${this.name}@${this.version}`); + } catch (error) { + logger.error(`[EXTENSION]: disabling ${this.name}@${this.version} threw an error: ${error}`); } } - async whenEnabled(handlers: () => Promise) { - const disposers: Function[] = []; - const unregisterHandlers = () => { - disposers.forEach(unregister => unregister()); - disposers.length = 0; - }; - const cancelReaction = reaction(() => this.isEnabled, async (isEnabled) => { - if (isEnabled) { - const handlerDisposers = await handlers(); - - disposers.push(...handlerDisposers); - } else { - unregisterHandlers(); - } - }, { - fireImmediately: true - }); - - return () => { - unregisterHandlers(); - cancelReaction(); - }; - } - - protected onActivate(): void { + protected onActivate(): Promise | void { return; } - protected onDeactivate(): void { + protected onDeactivate(): Promise | void { return; } }