From f63d10d0035d28411896318486d0ef108a330e83 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Tue, 4 Apr 2023 16:21:46 -0400 Subject: [PATCH] Try and fix exit code issue Signed-off-by: Sebastian Malton --- package-lock.json | 20 +++++ packages/core/package.json | 2 + packages/core/src/common/logger.injectable.ts | 45 ++++++++-- .../src/common/winston-logger.injectable.ts | 9 +- .../extension-discovery.ts | 14 ++-- .../extension-loader/extension-loader.ts | 7 +- .../quit-application-menu-item.injectable.ts | 9 +- .../main/stop-application-menu.injectable.ts | 2 - .../stop-checking-for-updates.injectable.ts | 2 - ...update-should-happen-on-quit.injectable.ts | 2 - .../stopping/main/stop-all.injectable.ts | 14 ++-- .../main/ipc-file-logger.injectable.ts | 2 +- .../main/stop-ipc-logging.injectable.ts | 4 +- ...ing-the-app-using-application-menu.test.ts | 20 ++--- .../stop-validating-weblinks.injectable.ts | 2 - .../stop-catalog-sync.injectable.ts | 4 +- packages/core/src/main/cluster/manager.ts | 8 -- .../features/exit-app.injectable.ts | 8 +- .../features/is-auto-updating.injectable.ts | 21 +++++ .../clean-up-deep-linking.injectable.ts | 2 - ...-dock-for-last-closed-window.injectable.ts | 4 +- ...-single-application-instance.injectable.ts | 6 +- .../setup-device-shutdown.injectable.ts | 6 +- ...efore-closing-of-application.injectable.ts | 83 +++++++++---------- ...setup-tracking-auto-updating.injectable.ts | 27 ++++++ .../core/src/main/lens-proxy/lens-proxy.ts | 9 +- ...close-file-transport-on-quit.injectable.ts | 27 ++++++ .../main/logger/file-transport.injectable.ts | 4 - .../create-electron-window.injectable.ts | 19 ++++- .../create-lens-window.injectable.ts | 22 ++--- .../runnable-tokens/phases.ts | 4 +- .../clean-up-shell-sessions.injectable.ts | 2 - .../emit-close-to-event-bus.injectable.ts | 4 +- .../flag-renderer-as-not-loaded.injectable.ts | 4 +- .../stop-kube-config-sync.injectable.ts | 2 - .../runnables/setup-lens-proxy.injectable.ts | 10 +-- .../stop-cluster-manager.injectable.ts | 13 +-- .../stop-services-and-exit-app.injectable.ts | 23 ++--- ...-theme-from-operating-system.injectable.ts | 2 - .../electron-tray/stop-tray.injectable.ts | 2 - .../menu-icon/stop-reactivity.injectable.ts | 2 - ...top-reactive-tray-menu-items.injectable.ts | 2 - .../quit-app-tray-item.injectable.ts | 37 +++------ .../run-many/src/run-many-for.ts | 6 +- .../utility-features/run-many/src/types.ts | 13 +++ 45 files changed, 301 insertions(+), 229 deletions(-) create mode 100644 packages/core/src/main/electron-app/features/is-auto-updating.injectable.ts create mode 100644 packages/core/src/main/electron-app/runnables/setup-tracking-auto-updating.injectable.ts create mode 100644 packages/core/src/main/logger/close-file-transport-on-quit.injectable.ts diff --git a/package-lock.json b/package-lock.json index 1a51f9796d..109bd36172 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10241,6 +10241,15 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "node_modules/@types/stoppable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/stoppable/-/stoppable-1.1.1.tgz", + "integrity": "sha512-b8N+fCADRIYYrGZOcmOR8ZNBOqhktWTB/bMUl5LvGtT201QKJZOOH5UsFyI3qtteM6ZAJbJqZoBcLqqxKIwjhw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tar": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.4.tgz", @@ -34430,6 +34439,15 @@ "node": ">= 0.4" } }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, "node_modules/stream-buffers": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", @@ -38200,6 +38218,7 @@ "rfc6902": "^5.0.1", "selfsigned": "^2.1.1", "semver": "^7.3.8", + "stoppable": "^1.1.0", "tar": "^6.1.13", "tcp-port-used": "^1.0.2", "tempy": "1.0.1", @@ -38260,6 +38279,7 @@ "@types/react-window": "^1.8.5", "@types/readable-stream": "^2.3.13", "@types/semver": "^7.3.13", + "@types/stoppable": "^1.1.1", "@types/tar": "^6.1.4", "@types/tcp-port-used": "^1.0.1", "@types/triple-beam": "^1.3.2", diff --git a/packages/core/package.json b/packages/core/package.json index c95a9bc2ee..e2e239b1a1 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -167,6 +167,7 @@ "rfc6902": "^5.0.1", "selfsigned": "^2.1.1", "semver": "^7.3.8", + "stoppable": "^1.1.0", "tar": "^6.1.13", "tcp-port-used": "^1.0.2", "tempy": "1.0.1", @@ -227,6 +228,7 @@ "@types/react-window": "^1.8.5", "@types/readable-stream": "^2.3.13", "@types/semver": "^7.3.13", + "@types/stoppable": "^1.1.1", "@types/tar": "^6.1.4", "@types/tcp-port-used": "^1.0.1", "@types/triple-beam": "^1.3.2", diff --git a/packages/core/src/common/logger.injectable.ts b/packages/core/src/common/logger.injectable.ts index e64978e44b..b599fde1c6 100644 --- a/packages/core/src/common/logger.injectable.ts +++ b/packages/core/src/common/logger.injectable.ts @@ -10,13 +10,48 @@ const loggerInjectable = getInjectable({ id: "logger", instantiate: (di): Logger => { const baseLogger = di.inject(winstonLoggerInjectable); + let closed = false; + + baseLogger.once("close", () => { + closed = true; + }); return { - debug: (message, ...data) => baseLogger.debug(message, ...data), - info: (message, ...data) => baseLogger.info(message, ...data), - warn: (message, ...data) => baseLogger.warn(message, ...data), - error: (message, ...data) => baseLogger.error(message, ...data), - silly: (message, ...data) => baseLogger.silly(message, ...data), + debug: (message, ...data) => { + if (closed) { + console.debug(message, ...data); + } else { + baseLogger.debug(message, ...data); + } + }, + info: (message, ...data) => { + if (closed) { + console.info(message, ...data); + } else { + baseLogger.info(message, ...data); + } + }, + warn: (message, ...data) => { + if (closed) { + console.warn(message, ...data); + } else { + baseLogger.warn(message, ...data); + } + }, + error: (message, ...data) => { + if (closed) { + console.error(message, ...data); + } else { + baseLogger.error(message, ...data); + } + }, + silly: (message, ...data) => { + if (closed) { + // DO nothing + } else { + baseLogger.silly(message, ...data); + } + }, }; }, diff --git a/packages/core/src/common/winston-logger.injectable.ts b/packages/core/src/common/winston-logger.injectable.ts index 481d520fac..b7a2b6a2f0 100644 --- a/packages/core/src/common/winston-logger.injectable.ts +++ b/packages/core/src/common/winston-logger.injectable.ts @@ -8,11 +8,10 @@ import { loggerTransportInjectionToken } from "./logger/transports"; const winstonLoggerInjectable = getInjectable({ id: "winston-logger", - instantiate: (di) => - createLogger({ - format: format.combine(format.splat(), format.simple()), - transports: di.injectMany(loggerTransportInjectionToken), - }), + instantiate: (di) => createLogger({ + format: format.combine(format.splat(), format.simple()), + transports: di.injectMany(loggerTransportInjectionToken), + }), }); export default winstonLoggerInjectable; diff --git a/packages/core/src/extensions/extension-discovery/extension-discovery.ts b/packages/core/src/extensions/extension-discovery/extension-discovery.ts index 7a39fa7467..f9cfd9a7bd 100644 --- a/packages/core/src/extensions/extension-discovery/extension-discovery.ts +++ b/packages/core/src/extensions/extension-discovery/extension-discovery.ts @@ -5,7 +5,7 @@ import { ipcRenderer } from "electron"; import { EventEmitter } from "events"; -import { makeObservable, observable, reaction, when } from "mobx"; +import { makeObservable, observable, reaction } from "mobx"; import { broadcastMessage, ipcMainHandle, ipcRendererOn } from "../../common/ipc"; import { toJS } from "../../common/utils"; import { isErrnoException } from "@k8slens/utilities"; @@ -31,6 +31,7 @@ import type { GetRelativePath } from "../../common/path/get-relative-path.inject import type { RemovePath } from "../../common/fs/remove.injectable"; import type TypedEventEmitter from "typed-emitter"; import type { IsExtensionEnabled } from "../../features/extensions/enabled/common/is-enabled.injectable"; +import assert from "assert"; interface Dependencies { readonly extensionLoader: ExtensionLoader; @@ -101,10 +102,6 @@ export class ExtensionDiscovery { // True if extensions have been loaded from the disk after app startup @observable isLoaded = false; - get whenLoaded() { - return when(() => this.isLoaded); - } - public readonly events: TypedEventEmitter = new EventEmitter(); constructor(protected readonly dependencies: Dependencies) { @@ -157,11 +154,10 @@ export class ExtensionDiscovery { * Watches for added/removed local extensions. * Dependencies are installed automatically after an extension folder is copied. */ - async watchExtensions(): Promise { - this.dependencies.logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`); + watchExtensions() { + assert(this.isLoaded, "This function can only be called after a call to 'load' has resolved"); - // Wait until .load() has been called and has been resolved - await this.whenLoaded; + this.dependencies.logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`); this.dependencies.watch(this.localFolderPath, { // For adding and removing symlinks to work, the depth has to be 1. diff --git a/packages/core/src/extensions/extension-loader/extension-loader.ts b/packages/core/src/extensions/extension-loader/extension-loader.ts index 4a24ad23a1..08cdd50760 100644 --- a/packages/core/src/extensions/extension-loader/extension-loader.ts +++ b/packages/core/src/extensions/extension-loader/extension-loader.ts @@ -69,10 +69,6 @@ export class ExtensionLoader { @observable isLoaded = false; - get whenLoaded() { - return when(() => this.isLoaded); - } - constructor(protected readonly dependencies: Dependencies) { makeObservable(this); @@ -138,10 +134,9 @@ export class ExtensionLoader { await this.initMain(); } else { await this.initRenderer(); + await when(() => this.isLoaded); } - await Promise.all([this.whenLoaded]); - // broadcasting extensions between main/renderer processes reaction(() => this.toJSON(), () => this.broadcastExtensions(), { fireImmediately: true, diff --git a/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/quit-application/quit-application-menu-item.injectable.ts b/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/quit-application/quit-application-menu-item.injectable.ts index 71f7cde125..090c3f039c 100644 --- a/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/quit-application/quit-application-menu-item.injectable.ts +++ b/packages/core/src/features/application-menu/main/menu-items/special-menu-for-mac-application/quit-application/quit-application-menu-item.injectable.ts @@ -4,28 +4,23 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import applicationMenuItemInjectionToken from "../../application-menu-item-injection-token"; -import stopServicesAndExitAppInjectable from "../../../../../../main/stop-services-and-exit-app.injectable"; +import quitAppExplicitlyInjectable from "../../../../../../main/stop-services-and-exit-app.injectable"; import isMacInjectable from "../../../../../../common/vars/is-mac.injectable"; const quitApplicationMenuItemInjectable = getInjectable({ id: "quit-application-menu-item", instantiate: (di) => { - const stopServicesAndExitApp = di.inject(stopServicesAndExitAppInjectable); const isMac = di.inject(isMacInjectable); return { kind: "clickable-menu-item" as const, id: "quit", label: "Quit", - parentId: isMac ? "mac" : "file", orderNumber: isMac ? 140 : 70, keyboardShortcut: isMac ? "Cmd+Q" : "Alt+F4", - - onClick: () => { - stopServicesAndExitApp(); - }, + onClick: di.inject(quitAppExplicitlyInjectable), }; }, diff --git a/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts b/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts index 816683b2de..86d6072728 100644 --- a/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts +++ b/packages/core/src/features/application-menu/main/stop-application-menu.injectable.ts @@ -14,8 +14,6 @@ const stopApplicationMenuInjectable = getInjectable({ const applicationMenu = di.inject(applicationMenuReactivityInjectable); applicationMenu.stop(); - - return undefined; }, }), diff --git a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts index df1557466e..c8533fc311 100644 --- a/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts +++ b/packages/core/src/features/application-update/child-features/periodical-checking-of-updates/main/stop-checking-for-updates.injectable.ts @@ -16,8 +16,6 @@ const stopCheckingForUpdatesInjectable = getInjectable({ if (periodicalCheckForUpdates.started) { periodicalCheckForUpdates.stop(); } - - return undefined; }, }), diff --git a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts index 36a6d3174d..86dd12682e 100644 --- a/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts +++ b/packages/core/src/features/application-update/main/watch-if-update-should-happen-on-quit/stop-watching-if-update-should-happen-on-quit.injectable.ts @@ -14,8 +14,6 @@ const stopWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({ const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable); watchIfUpdateShouldHappenOnQuit.stop(); - - return undefined; }, }), diff --git a/packages/core/src/features/extensions/stopping/main/stop-all.injectable.ts b/packages/core/src/features/extensions/stopping/main/stop-all.injectable.ts index ce3d69d723..50400ee6d2 100644 --- a/packages/core/src/features/extensions/stopping/main/stop-all.injectable.ts +++ b/packages/core/src/features/extensions/stopping/main/stop-all.injectable.ts @@ -5,21 +5,23 @@ import { getInjectable } from "@ogre-tools/injectable"; import extensionInjectable from "../../../../extensions/extension-loader/extension/extension.injectable"; import extensionsInjectable from "../../../../extensions/extensions.injectable"; +import { beforeQuitOfBackEndInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases"; const stopAllExtensionsInjectable = getInjectable({ id: "stop-all-extensions", - instantiate: (di) => { - const extensionInstances = di.inject(extensionsInjectable); + instantiate: (di) => ({ + run: async () => { + const instances = di.inject(extensionsInjectable).get(); - return async () => { - for (const instance of extensionInstances.get()) { + for (const instance of instances) { const extension = di.inject(extensionInjectable, instance); await instance.disable(); extension.deregister(); } - }; - }, + }, + }), + injectionToken: beforeQuitOfBackEndInjectionToken, }); export default stopAllExtensionsInjectable; diff --git a/packages/core/src/features/population-of-logs-to-a-file/main/ipc-file-logger.injectable.ts b/packages/core/src/features/population-of-logs-to-a-file/main/ipc-file-logger.injectable.ts index df82ef7c6b..3a65c58c29 100644 --- a/packages/core/src/features/population-of-logs-to-a-file/main/ipc-file-logger.injectable.ts +++ b/packages/core/src/features/population-of-logs-to-a-file/main/ipc-file-logger.injectable.ts @@ -26,7 +26,7 @@ const ipcFileLoggerInjectable = getInjectable({ () => createIpcFileTransport(fileId), ); - transport?.log?.(entry, () => {}); + transport.log?.(entry, () => {}); } function close(fileId: string) { diff --git a/packages/core/src/features/population-of-logs-to-a-file/main/stop-ipc-logging.injectable.ts b/packages/core/src/features/population-of-logs-to-a-file/main/stop-ipc-logging.injectable.ts index 89533411ca..bcf96cb60a 100644 --- a/packages/core/src/features/population-of-logs-to-a-file/main/stop-ipc-logging.injectable.ts +++ b/packages/core/src/features/population-of-logs-to-a-file/main/stop-ipc-logging.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases"; import ipcFileLoggerInjectable from "./ipc-file-logger.injectable"; const stopIpcLoggingInjectable = getInjectable({ @@ -21,7 +21,7 @@ const stopIpcLoggingInjectable = getInjectable({ }; }, - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default stopIpcLoggingInjectable; diff --git a/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts b/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts index c145842828..778572f7d1 100644 --- a/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts +++ b/packages/core/src/features/quitting-and-restarting-the-app/quitting-the-app-using-application-menu.test.ts @@ -6,16 +6,16 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder"; import type { ClusterManager } from "../../main/cluster/manager"; -import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable"; +import quitAppInjectable from "../../main/electron-app/features/exit-app.injectable"; import clusterManagerInjectable from "../../main/cluster/manager.injectable"; -import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable"; +import quitAppExplicitlyInjectable from "../../main/stop-services-and-exit-app.injectable"; import { testUsingFakeTime, advanceFakeTime } from "../../test-utils/use-fake-time"; describe("quitting the app using application menu", () => { describe("given application has started", () => { let builder: ApplicationBuilder; let clusterManagerStub: ClusterManager; - let exitAppMock: jest.Mock; + let quitAppMock: jest.Mock; beforeEach(async () => { testUsingFakeTime("2015-10-21T07:28:00Z"); @@ -23,13 +23,13 @@ describe("quitting the app using application menu", () => { builder = getApplicationBuilder(); builder.beforeApplicationStart(({ mainDi }) => { - mainDi.unoverride(stopServicesAndExitAppInjectable); + mainDi.unoverride(quitAppExplicitlyInjectable); clusterManagerStub = { stop: jest.fn() } as unknown as ClusterManager; mainDi.override(clusterManagerInjectable, () => clusterManagerStub); - exitAppMock = jest.fn(); - mainDi.override(exitAppInjectable, () => exitAppMock); + quitAppMock = jest.fn(); + mainDi.override(quitAppInjectable, () => quitAppMock); }); await builder.render(); @@ -52,14 +52,10 @@ describe("quitting the app using application menu", () => { expect(windows).toEqual([]); }); - it("disconnects all clusters", () => { - expect(clusterManagerStub.stop).toHaveBeenCalled(); - }); - it("after insufficient time passes, does not terminate application yet", () => { advanceFakeTime(999); - expect(exitAppMock).not.toHaveBeenCalled(); + expect(quitAppMock).not.toHaveBeenCalled(); }); describe("after sufficient time passes", () => { @@ -68,7 +64,7 @@ describe("quitting the app using application menu", () => { }); it("terminates application", () => { - expect(exitAppMock).toHaveBeenCalled(); + expect(quitAppMock).toHaveBeenCalled(); }); }); }); diff --git a/packages/core/src/features/weblinks/main/stop-validating-weblinks.injectable.ts b/packages/core/src/features/weblinks/main/stop-validating-weblinks.injectable.ts index 221a3ee0dd..96bc06647d 100644 --- a/packages/core/src/features/weblinks/main/stop-validating-weblinks.injectable.ts +++ b/packages/core/src/features/weblinks/main/stop-validating-weblinks.injectable.ts @@ -13,8 +13,6 @@ const stopValidatingWeblinksInjectable = getInjectable({ const weblinkVerificationStartableStoppable = di.inject(weblinkVerificationStartableStoppableInjectable); weblinkVerificationStartableStoppable.stop(); - - return undefined; }, }), injectionToken: beforeQuitOfBackEndInjectionToken, diff --git a/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts b/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts index faf5013a5f..0ab32646ef 100644 --- a/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts +++ b/packages/core/src/main/catalog-sync-to-renderer/stop-catalog-sync.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import catalogSyncToRendererInjectable from "./catalog-sync-to-renderer.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/phases"; const stopCatalogSyncInjectable = getInjectable({ id: "stop-catalog-sync", @@ -21,7 +21,7 @@ const stopCatalogSyncInjectable = getInjectable({ }, }), - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default stopCatalogSyncInjectable; diff --git a/packages/core/src/main/cluster/manager.ts b/packages/core/src/main/cluster/manager.ts index 800f981372..f52050ffa4 100644 --- a/packages/core/src/main/cluster/manager.ts +++ b/packages/core/src/main/cluster/manager.ts @@ -226,14 +226,6 @@ export class ClusterManager { )), ); }; - - stop() { - for (const cluster of this.dependencies.clusters.get()) { - this.dependencies - .getClusterConnection(cluster) - .disconnect(); - } - } } export function catalogEntityFromCluster(cluster: Cluster) { diff --git a/packages/core/src/main/electron-app/features/exit-app.injectable.ts b/packages/core/src/main/electron-app/features/exit-app.injectable.ts index 0734b4c8c5..87d418c347 100644 --- a/packages/core/src/main/electron-app/features/exit-app.injectable.ts +++ b/packages/core/src/main/electron-app/features/exit-app.injectable.ts @@ -5,14 +5,14 @@ import { getInjectable } from "@ogre-tools/injectable"; import electronAppInjectable from "../electron-app.injectable"; -const exitAppInjectable = getInjectable({ - id: "exit-app", +const quitAppInjectable = getInjectable({ + id: "quit-app", instantiate: (di) => () => { const app = di.inject(electronAppInjectable); - app.exit(0); + app.quit(); }, }); -export default exitAppInjectable; +export default quitAppInjectable; diff --git a/packages/core/src/main/electron-app/features/is-auto-updating.injectable.ts b/packages/core/src/main/electron-app/features/is-auto-updating.injectable.ts new file mode 100644 index 0000000000..c598762f14 --- /dev/null +++ b/packages/core/src/main/electron-app/features/is-auto-updating.injectable.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; + +const isAutoUpdatingInjectable = getInjectable({ + id: "is-auto-updating", + instantiate: () => { + let value = false; + + return { + get: () => value, + set: (newValue: boolean) => { + value = newValue; + }, + }; + }, +}); + +export default isAutoUpdatingInjectable; diff --git a/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts b/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts index 19fb7e1143..737562270b 100644 --- a/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/clean-up-deep-linking.injectable.ts @@ -14,8 +14,6 @@ const cleanUpDeepLinkingInjectable = getInjectable({ const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); lensProtocolRouterMain.cleanup(); - - return undefined; }, }), diff --git a/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts b/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts index e61af65da4..421a7c8830 100644 --- a/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/dock-visibility/hide-dock-for-last-closed-window.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../../electron-app.injectable"; import { isEmpty } from "lodash/fp"; import getVisibleWindowsInjectable from "../../../start-main-application/lens-window/get-visible-windows.injectable"; @@ -25,7 +25,7 @@ const hideDockForLastClosedWindowInjectable = getInjectable({ }, }), - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default hideDockForLastClosedWindowInjectable; diff --git a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts index 3dfe63430d..67a57d19ad 100644 --- a/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/enforce-single-application-instance.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; import requestSingleInstanceLockInjectable from "../features/request-single-instance-lock.injectable"; -import exitAppInjectable from "../features/exit-app.injectable"; +import quitAppInjectable from "../features/exit-app.injectable"; const enforceSingleApplicationInstanceInjectable = getInjectable({ id: "enforce-single-application-instance", @@ -13,10 +13,10 @@ const enforceSingleApplicationInstanceInjectable = getInjectable({ instantiate: (di) => ({ run: () => { const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable); - const exitApp = di.inject(exitAppInjectable); + const quitApp = di.inject(quitAppInjectable); if (!requestSingleInstanceLock()) { - exitApp(); + quitApp(); } return undefined; diff --git a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts index c1ddeae175..c09d2d5594 100644 --- a/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-device-shutdown.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import powerMonitorInjectable from "../features/power-monitor.injectable"; -import exitAppInjectable from "../features/exit-app.injectable"; +import quitAppInjectable from "../features/exit-app.injectable"; import { onLoadOfApplicationInjectionToken } from "@k8slens/application"; const setupDeviceShutdownInjectable = getInjectable({ @@ -13,9 +13,9 @@ const setupDeviceShutdownInjectable = getInjectable({ instantiate: (di) => ({ run: () => { const powerMonitor = di.inject(powerMonitorInjectable); - const exitApp = di.inject(exitAppInjectable); + const quitApp = di.inject(quitAppInjectable); - powerMonitor.on("shutdown", exitApp); + powerMonitor.on("shutdown", quitApp); }, }), diff --git a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts index 9843d2c223..2fbe1c0f27 100644 --- a/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts +++ b/packages/core/src/main/electron-app/runnables/setup-runnables-before-closing-of-application.injectable.ts @@ -4,11 +4,11 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; -import { beforeQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases"; import electronAppInjectable from "../electron-app.injectable"; import isIntegrationTestingInjectable from "../../../common/vars/is-integration-testing.injectable"; -import autoUpdaterInjectable from "../features/auto-updater.injectable"; import { runManySyncFor, runManyFor } from "@k8slens/run-many"; +import quitAppInjectable from "../features/exit-app.injectable"; const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({ id: "setup-closing-of-application", @@ -17,54 +17,51 @@ const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({ run: () => { const runManySync = runManySyncFor(di); const runMany = runManyFor(di); - const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken); + const runRunnablesAfterQuitOfFrontEnd = runManySync(afterQuitOfFrontEndInjectionToken); const runRunnablesBeforeQuitOfBackEnd = runMany(beforeQuitOfBackEndInjectionToken); const app = di.inject(electronAppInjectable); const isIntegrationTesting = di.inject(isIntegrationTestingInjectable); - const autoUpdater = di.inject(autoUpdaterInjectable); - let isAutoUpdating = false; + const quitApp = di.inject(quitAppInjectable); - autoUpdater.on("before-quit-for-update", () => { - isAutoUpdating = true; + let isAsyncQuitting = false; + + const doAsyncQuit = () => { + if (isAsyncQuitting) { + return; + } + + isAsyncQuitting = true; + + void (async () => { + try { + console.log("before runRunnablesBeforeQuitOfBackEnd"); + await runRunnablesBeforeQuitOfBackEnd(); + console.log("after runRunnablesBeforeQuitOfBackEnd"); + app.exit(0); + } catch (error) { + console.error("A beforeQuitOfBackEnd failed!!!!", error); + app.exit(1); + } + })(); + }; + + app.on("window-all-closed", () => { + console.log(`app.on("window-all-closed")`); + runRunnablesAfterQuitOfFrontEnd(); + + if (isIntegrationTesting) { + quitApp(); + } }); - app.on("will-quit", () => { - runRunnablesBeforeQuitOfFrontEnd(); + app.on("will-quit", (event) => { + console.log(`app.on("will-quit")`); + event.preventDefault(); + doAsyncQuit(); + }); - let isAsyncQuitting = false; - - const doAsyncQuit = (event: Electron.Event, exitCode = 0) => { - if (isAsyncQuitting) { - return; - } - - isAsyncQuitting = true; - - void (async () => { - try { - await runRunnablesBeforeQuitOfBackEnd(); - } catch (error) { - console.error("A beforeQuitOfBackEnd failed!!!!", error); - exitCode = 1; - } - - app.exit(exitCode); - })(); - }; - - app.on("will-quit", (event) => { - runRunnablesBeforeQuitOfFrontEnd(); - event.preventDefault(); - - if (isIntegrationTesting || isAutoUpdating) { - doAsyncQuit(event); - } - }); - - app.on("quit", (event, exitCode) => { - event.preventDefault(); - doAsyncQuit(event, exitCode); - }); + app.on("quit", () => { + console.log(`app.on("quit")`); }); return undefined; diff --git a/packages/core/src/main/electron-app/runnables/setup-tracking-auto-updating.injectable.ts b/packages/core/src/main/electron-app/runnables/setup-tracking-auto-updating.injectable.ts new file mode 100644 index 0000000000..e42e72f8fa --- /dev/null +++ b/packages/core/src/main/electron-app/runnables/setup-tracking-auto-updating.injectable.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main"; +import { getInjectable } from "@ogre-tools/injectable"; +import autoUpdaterInjectable from "../features/auto-updater.injectable"; +import isAutoUpdatingInjectable from "../features/is-auto-updating.injectable"; + +const setupTrackingAutoUpdatingInjectable = getInjectable({ + id: "setup-tracking-auto-updating", + instantiate: (di) => ({ + run: () => { + const isAutoUpdating = di.inject(isAutoUpdatingInjectable); + const autoUpdater = di.inject(autoUpdaterInjectable); + + autoUpdater.on("before-quit-for-update", () => { + isAutoUpdating.set(true); + }); + + return undefined; + }, + }), + injectionToken: beforeElectronIsReadyInjectionToken, +}); + +export default setupTrackingAutoUpdatingInjectable; diff --git a/packages/core/src/main/lens-proxy/lens-proxy.ts b/packages/core/src/main/lens-proxy/lens-proxy.ts index ce5a54bdf1..36af9bd93f 100644 --- a/packages/core/src/main/lens-proxy/lens-proxy.ts +++ b/packages/core/src/main/lens-proxy/lens-proxy.ts @@ -18,6 +18,7 @@ import type { EmitAppEvent } from "../../common/app-event-bus/emit-event.injecta import type { Logger } from "../../common/logger"; import type { SelfSignedCert } from "selfsigned"; import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable"; +import stoppable from "stoppable"; export type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined; export type ServerIncomingMessage = SetRequired; @@ -65,14 +66,14 @@ const disallowedPorts = new Set([ ]); export class LensProxy { - protected proxyServer: https.Server; + protected proxyServer: https.Server & stoppable.WithStop; protected closed = false; protected retryCounters = new Map(); constructor(private readonly dependencies: Dependencies) { this.configureProxy(dependencies.proxy); - this.proxyServer = https.createServer( + this.proxyServer = stoppable(https.createServer( { key: dependencies.certificate.private, cert: dependencies.certificate.cert, @@ -80,7 +81,7 @@ export class LensProxy { (req, res) => { this.handleRequest(req as ServerIncomingMessage, res); }, - ); + ), 500); this.proxyServer .on("upgrade", (req: ServerIncomingMessage, socket: net.Socket, head: Buffer) => { @@ -175,7 +176,7 @@ export class LensProxy { this.dependencies.logger.info("[LENS-PROXY]: Closing server"); return new Promise((resolve) => { - this.proxyServer.close(() => resolve()); + this.proxyServer.stop(() => resolve()); }); } diff --git a/packages/core/src/main/logger/close-file-transport-on-quit.injectable.ts b/packages/core/src/main/logger/close-file-transport-on-quit.injectable.ts new file mode 100644 index 0000000000..4799f7bc4a --- /dev/null +++ b/packages/core/src/main/logger/close-file-transport-on-quit.injectable.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { loggerTransportInjectionToken } from "../../common/logger/transports"; +import winstonLoggerInjectable from "../../common/winston-logger.injectable"; +import { beforeQuitOfBackEndInjectionToken } from "../start-main-application/runnable-tokens/phases"; + +const closeLoggerOnQuitInjectable = getInjectable({ + id: "close-file-transport-on-quit", + instantiate: (di) => ({ + run: () => { + const transports = di.injectMany(loggerTransportInjectionToken); + const winstonLogger = di.inject(winstonLoggerInjectable); + + winstonLogger.close(); + + for (const transport of transports) { + transport.close?.(); + } + }, + }), + injectionToken: beforeQuitOfBackEndInjectionToken, +}); + +export default closeLoggerOnQuitInjectable; diff --git a/packages/core/src/main/logger/file-transport.injectable.ts b/packages/core/src/main/logger/file-transport.injectable.ts index c71b44a2a0..3a47692747 100644 --- a/packages/core/src/main/logger/file-transport.injectable.ts +++ b/packages/core/src/main/logger/file-transport.injectable.ts @@ -13,10 +13,6 @@ const fileLoggerTransportInjectable = getInjectable({ handleExceptions: false, level: "debug", filename: "lens.log", - /** - * SAFTEY: the `ipcMain` check above should mean that this is only - * called in the main process - */ dirname: di.inject(directoryForLogsInjectable), maxsize: 1024 * 1024, maxFiles: 16, diff --git a/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts b/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts index 0693c71643..86ee959c3e 100644 --- a/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/application-window/create-electron-window.injectable.ts @@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable"; import loggerInjectable from "../../../../common/logger.injectable"; import applicationWindowStateInjectable from "./application-window-state.injectable"; import { BrowserWindow } from "electron"; -import type { ElectronWindow } from "./create-lens-window.injectable"; import type { RequireExactlyOne } from "type-fest"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable"; @@ -15,6 +14,7 @@ import isLinuxInjectable from "../../../../common/vars/is-linux.injectable"; import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable"; import { applicationInformationToken } from "@k8slens/application"; import sessionCertificateVerifierInjectable from "./session-certificate-verifier.injectable"; +import type { ClusterFrameInfo } from "../../../../common/cluster-frames.injectable"; export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover"; @@ -43,6 +43,21 @@ export interface ElectronWindowConfiguration { onDomReady?: () => void; } +export interface ElectronWindow { + show: () => void; + close: () => void; + send: (args: SendToViewArgs) => void; + loadFile: (filePath: string) => Promise; + loadUrl: (url: string) => Promise; + reload: () => void; +} + +export interface SendToViewArgs { + channel: string; + frameInfo?: ClusterFrameInfo; + data?: unknown; +} + export type CreateElectronWindow = (config: ElectronWindowConfiguration) => ElectronWindow; const createElectronWindowInjectable = getInjectable({ @@ -158,7 +173,6 @@ const createElectronWindowInjectable = getInjectable({ await browserWindow.loadFile(filePath); }, - loadUrl: async (url) => { logger.info( `[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from url: ${url}...`, @@ -166,7 +180,6 @@ const createElectronWindowInjectable = getInjectable({ await browserWindow.loadURL(url); }, - show: () => browserWindow.show(), close: () => browserWindow.close(), send: ({ channel, data, frameInfo }) => { diff --git a/packages/core/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts b/packages/core/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts index 3d6e636c8a..170779858e 100644 --- a/packages/core/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/application-window/create-lens-window.injectable.ts @@ -3,24 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import type { ContentSource, ElectronWindowTitleBarStyle } from "./create-electron-window.injectable"; +import type { ContentSource, ElectronWindow, ElectronWindowTitleBarStyle, SendToViewArgs } from "./create-electron-window.injectable"; import createElectronWindowInjectable from "./create-electron-window.injectable"; -import type { ClusterFrameInfo } from "../../../../common/cluster-frames.injectable"; - -export interface ElectronWindow { - show: () => void; - close: () => void; - send: (args: SendToViewArgs) => void; - loadFile: (filePath: string) => Promise; - loadUrl: (url: string) => Promise; - reload: () => void; -} - -export interface SendToViewArgs { - channel: string; - frameInfo?: ClusterFrameInfo; - data?: unknown; -} export interface LensWindow { id: string; @@ -91,6 +75,7 @@ const createLensWindowInjectable = getInjectable({ if (!browserWindow) { windowIsStarting = true; + console.log("BEFORE createElectronWindow"); browserWindow = createElectronWindow({ ...configuration, onClose: () => { @@ -104,11 +89,14 @@ const createLensWindowInjectable = getInjectable({ url: urlForContent, } = configuration.getContentSource(); + console.log("BEFORE configuration.beforeOpen?.()"); const beforeOpen = configuration.beforeOpen?.(); if (filePathForContent) { + console.log("BEFORE browserWindow.loadFile"); await browserWindow.loadFile(filePathForContent); } else if (urlForContent) { + console.log("BEFORE browserWindow.loadUrl"); await browserWindow.loadUrl(urlForContent); } diff --git a/packages/core/src/main/start-main-application/runnable-tokens/phases.ts b/packages/core/src/main/start-main-application/runnable-tokens/phases.ts index b5844436e1..4557477fc9 100644 --- a/packages/core/src/main/start-main-application/runnable-tokens/phases.ts +++ b/packages/core/src/main/start-main-application/runnable-tokens/phases.ts @@ -6,8 +6,8 @@ import { getInjectionToken } from "@ogre-tools/injectable"; import type { Runnable, RunnableSync } from "@k8slens/run-many"; -export const beforeQuitOfFrontEndInjectionToken = getInjectionToken({ - id: "before-quit-of-front-end", +export const afterQuitOfFrontEndInjectionToken = getInjectionToken({ + id: "after-quit-of-front-end", }); export const beforeQuitOfBackEndInjectionToken = getInjectionToken({ diff --git a/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts b/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts index fd428dd1fe..573a7b1597 100644 --- a/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/clean-up-shell-sessions.injectable.ts @@ -26,8 +26,6 @@ const cleanUpShellSessionsInjectable = getInjectable({ } shellSessionProcesses.clear(); - - return undefined; }, }), diff --git a/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts b/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts index cbd7a2d289..3704ab72d5 100644 --- a/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/emit-close-to-event-bus.injectable.ts @@ -4,7 +4,7 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; const emitCloseToEventBusInjectable = getInjectable({ id: "emit-close-to-event-bus", @@ -19,7 +19,7 @@ const emitCloseToEventBusInjectable = getInjectable({ }, }), - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default emitCloseToEventBusInjectable; diff --git a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts index 899b234f39..e46abdd85b 100644 --- a/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/flag-renderer/flag-renderer-as-not-loaded.injectable.ts @@ -5,7 +5,7 @@ import { getInjectable } from "@ogre-tools/injectable"; import { runInAction } from "mobx"; import lensProtocolRouterMainInjectable from "../../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../../runnable-tokens/phases"; +import { afterQuitOfFrontEndInjectionToken } from "../../runnable-tokens/phases"; const flagRendererAsNotLoadedInjectable = getInjectable({ id: "stop-deep-linking", @@ -23,7 +23,7 @@ const flagRendererAsNotLoadedInjectable = getInjectable({ }, }), - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default flagRendererAsNotLoadedInjectable; diff --git a/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts b/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts index 118dac2ed4..f314aa52f4 100644 --- a/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/kube-config-sync/stop-kube-config-sync.injectable.ts @@ -14,8 +14,6 @@ const stopKubeConfigSyncInjectable = getInjectable({ const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable); kubeConfigSyncManager.stopSync(); - - return undefined; }, }), diff --git a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts index c77a0470be..89b58224db 100644 --- a/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/setup-lens-proxy.injectable.ts @@ -3,7 +3,7 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import exitAppInjectable from "../../electron-app/features/exit-app.injectable"; +import quitAppInjectable from "../../electron-app/features/exit-app.injectable"; import lensProxyInjectable from "../../lens-proxy/lens-proxy.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import lensProxyPortInjectable from "../../lens-proxy/lens-proxy-port.injectable"; @@ -22,7 +22,7 @@ const setupLensProxyInjectable = getInjectable({ instantiate: (di) => ({ run: async () => { const lensProxy = di.inject(lensProxyInjectable); - const exitApp = di.inject(exitAppInjectable); + const quitApp = di.inject(quitAppInjectable); const logger = di.inject(loggerInjectable); const lensProxyPort = di.inject(lensProxyPortInjectable); const isWindows = di.inject(isWindowsInjectable); @@ -37,7 +37,7 @@ const setupLensProxyInjectable = getInjectable({ } catch (error: any) { showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); - return exitApp(); + return quitApp(); } // test proxy connection @@ -54,7 +54,7 @@ const setupLensProxyInjectable = getInjectable({ if (buildVersion.get() !== versionFromProxy) { logger.error("Proxy server responded with invalid response"); - return exitApp(); + return quitApp(); } logger.info("⚡ LensProxy connection OK"); @@ -73,7 +73,7 @@ const setupLensProxyInjectable = getInjectable({ showErrorPopup("Lens Proxy Error", message.join("\n\n")); - return exitApp(); + return quitApp(); } }, runAfter: initializeBuildVersionInjectable, diff --git a/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts b/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts index f26feb01d7..9e52b01f62 100644 --- a/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts +++ b/packages/core/src/main/start-main-application/runnables/stop-cluster-manager.injectable.ts @@ -3,23 +3,26 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import clusterManagerInjectable from "../../cluster/manager.injectable"; -import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; +import clustersInjectable from "../../../features/cluster/storage/common/clusters.injectable"; +import clusterConnectionInjectable from "../../cluster/cluster-connection.injectable"; +import { afterQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases"; const stopClusterManagerInjectable = getInjectable({ id: "stop-cluster-manager", instantiate: (di) => ({ run: () => { - const clusterManager = di.inject(clusterManagerInjectable); + const clusters = di.inject(clustersInjectable); - clusterManager.stop(); + for (const cluster of clusters.get()) { + di.inject(clusterConnectionInjectable, cluster).disconnect(); + } return undefined; }, }), - injectionToken: beforeQuitOfFrontEndInjectionToken, + injectionToken: afterQuitOfFrontEndInjectionToken, }); export default stopClusterManagerInjectable; diff --git a/packages/core/src/main/stop-services-and-exit-app.injectable.ts b/packages/core/src/main/stop-services-and-exit-app.injectable.ts index f9bd436818..feae6c208e 100644 --- a/packages/core/src/main/stop-services-and-exit-app.injectable.ts +++ b/packages/core/src/main/stop-services-and-exit-app.injectable.ts @@ -3,33 +3,24 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import exitAppInjectable from "./electron-app/features/exit-app.injectable"; -import clusterManagerInjectable from "./cluster/manager.injectable"; +import quitAppInjectable from "./electron-app/features/exit-app.injectable"; import loggerInjectable from "../common/logger.injectable"; -import closeAllWindowsInjectable from "./start-main-application/lens-window/hide-all-windows/close-all-windows.injectable"; import emitAppEventInjectable from "../common/app-event-bus/emit-event.injectable"; -import stopAllExtensionsInjectable from "../features/extensions/stopping/main/stop-all.injectable"; -const stopServicesAndExitAppInjectable = getInjectable({ - id: "stop-services-and-exit-app", +const quitAppExplicitlyInjectable = getInjectable({ + id: "quit-app-explicitly", instantiate: (di) => { - const exitApp = di.inject(exitAppInjectable); - const clusterManager = di.inject(clusterManagerInjectable); + const quitApp = di.inject(quitAppInjectable); const logger = di.inject(loggerInjectable); - const closeAllWindows = di.inject(closeAllWindowsInjectable); const emitAppEvent = di.inject(emitAppEventInjectable); - const stopAllExtensions = di.inject(stopAllExtensionsInjectable); - return async () => { + return () => { emitAppEvent({ name: "service", action: "close" }); - closeAllWindows(); - clusterManager.stop(); - await stopAllExtensions(); logger.info("SERVICE:QUIT"); - setTimeout(exitApp, 1000); + quitApp(); }; }, }); -export default stopServicesAndExitAppInjectable; +export default quitAppExplicitlyInjectable; diff --git a/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts b/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts index f50a298822..5d75a70961 100644 --- a/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts +++ b/packages/core/src/main/theme/sync-theme-from-os/stop-syncing-theme-from-operating-system.injectable.ts @@ -14,8 +14,6 @@ const stopSyncingThemeFromOperatingSystemInjectable = getInjectable({ const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable); syncTheme.stop(); - - return undefined; }, }), diff --git a/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts b/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts index 4bd6bd6c3a..c45a0c91b4 100644 --- a/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts +++ b/packages/core/src/main/tray/electron-tray/stop-tray.injectable.ts @@ -15,8 +15,6 @@ const stopTrayInjectable = getInjectable({ const electronTray = di.inject(electronTrayInjectable); electronTray.stop(); - - return undefined; }, runAfter: stopReactiveTrayMenuItemsInjectable, }), diff --git a/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts b/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts index b5908104d2..f3bf252954 100644 --- a/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts +++ b/packages/core/src/main/tray/menu-icon/stop-reactivity.injectable.ts @@ -14,8 +14,6 @@ const stopReactiveTrayMenuIconInjectable = getInjectable({ const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable); reactiveTrayMenuIcon.stop(); - - return undefined; }, }), diff --git a/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts b/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts index d5e5063e92..07b088c29e 100644 --- a/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts +++ b/packages/core/src/main/tray/reactive-tray-menu-items/stop-reactive-tray-menu-items.injectable.ts @@ -14,8 +14,6 @@ const stopReactiveTrayMenuItemsInjectable = getInjectable({ const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable); reactiveTrayMenuItems.stop(); - - return undefined; }, }), diff --git a/packages/core/src/main/tray/tray-menu-item/implementations/quit-app-tray-item.injectable.ts b/packages/core/src/main/tray/tray-menu-item/implementations/quit-app-tray-item.injectable.ts index 894a823511..0039c648ca 100644 --- a/packages/core/src/main/tray/tray-menu-item/implementations/quit-app-tray-item.injectable.ts +++ b/packages/core/src/main/tray/tray-menu-item/implementations/quit-app-tray-item.injectable.ts @@ -5,37 +5,20 @@ import { getInjectable } from "@ogre-tools/injectable"; import { trayMenuItemInjectionToken } from "../tray-menu-item-injection-token"; import { computed } from "mobx"; -import stopServicesAndExitAppInjectable from "../../../stop-services-and-exit-app.injectable"; -import { withErrorSuppression } from "../../../../common/utils/with-error-suppression/with-error-suppression"; -import { pipeline } from "@ogre-tools/fp"; -import withErrorLoggingInjectable from "../../../../common/utils/with-error-logging/with-error-logging.injectable"; +import quitAppExplicitlyInjectable from "../../../stop-services-and-exit-app.injectable"; const quitAppTrayItemInjectable = getInjectable({ id: "quit-app-tray-item", - instantiate: (di) => { - const stopServicesAndExitApp = di.inject(stopServicesAndExitAppInjectable); - const withErrorLoggingFor = di.inject(withErrorLoggingInjectable); - - return { - id: "quit-app", - parentId: null, - orderNumber: 150, - label: computed(() => "Quit App"), - enabled: computed(() => true), - visible: computed(() => true), - - click: pipeline( - stopServicesAndExitApp, - - withErrorLoggingFor(() => "[TRAY]: Quitting application failed."), - - // TODO: Find out how to improve typing so that instead of - // x => withErrorSuppression(x) there could only be withErrorSuppression - (x) => withErrorSuppression(x), - ), - }; - }, + instantiate: (di) => ({ + id: "quit-app", + parentId: null, + orderNumber: 150, + label: computed(() => "Quit App"), + enabled: computed(() => true), + visible: computed(() => true), + click: di.inject(quitAppExplicitlyInjectable), + }), injectionToken: trayMenuItemInjectionToken, }); diff --git a/packages/utility-features/run-many/src/run-many-for.ts b/packages/utility-features/run-many/src/run-many-for.ts index 4d33c009e2..393816278e 100644 --- a/packages/utility-features/run-many/src/run-many-for.ts +++ b/packages/utility-features/run-many/src/run-many-for.ts @@ -44,7 +44,7 @@ class DynamicBarrier { } } -const executeRunnableWith = (param: Param) => { +const executeRunnableWith = (tokenId: string, param: Param) => { const barrier = new DynamicBarrier(); return async (runnable: RunnableWithId): Promise => { @@ -52,7 +52,9 @@ const executeRunnableWith = (param: Param) => { await barrier.blockOn(parentRunnable.id); } + console.log(`^^^ "${tokenId}" @ "${runnable.id}"`) await runnable.run(param); + console.log(`--- "${tokenId}" @ "${runnable.id}"`) barrier.setFinished(runnable.id); }; }; @@ -61,7 +63,7 @@ export function runManyFor(di: DiContainerForInjection): RunMany { const convertToWithId = convertToWithIdWith(di); return (injectionToken: InjectionToken, void>) => async (param: Param) => { - const executeRunnable = executeRunnableWith(param); + const executeRunnable = executeRunnableWith(injectionToken.id, param); const allRunnables = di.injectManyWithMeta(injectionToken).map(x => convertToWithId(x)); verifyRunnablesAreDAG(injectionToken.id, allRunnables); diff --git a/packages/utility-features/run-many/src/types.ts b/packages/utility-features/run-many/src/types.ts index 007d9bcef1..014d075ef2 100644 --- a/packages/utility-features/run-many/src/types.ts +++ b/packages/utility-features/run-many/src/types.ts @@ -12,6 +12,13 @@ export interface Runnable { id?: never; run: Run; readonly runAfter?: SingleOrMany, Runnable, void>>; + /** + * Allows for specifying an black box ordering so that some runnables can be run at the end of the phase in + * a sorted order but after all other ones + * + * NOTE: Must be exclusively set to `runAfter` + */ + readonly afterOrderNumber?: number; } export interface RunnableWithId { @@ -20,6 +27,12 @@ export interface RunnableWithId { readonly runAfter: RunnableWithId[]; } +export interface AfterRunnableWithId { + run: Run; + readonly id: string; + readonly runAfter: number; +} + export interface RunnableSync { id?: never; run: RunSync;