1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix Catalog being empty after subsequent opens

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-05-17 17:05:27 -04:00
parent 22da7a9757
commit dbf130d920
14 changed files with 66 additions and 105 deletions

View File

@ -27,7 +27,7 @@ import { IReactionOptions, observable, reaction, runInAction, when } from "mobx"
import Singleton from "./utils/singleton";
import { getAppVersion } from "./utils/app-version";
import logger from "../main/logger";
import { broadcastMessage, subscribeToBroadcast, unsubscribeFromBroadcast } from "./ipc";
import { broadcastMessage, subscribeToBroadcast } from "./ipc";
import isEqual from "lodash/isEqual";
export interface BaseStoreParams<T = any> extends ConfOptions<T> {
@ -123,8 +123,7 @@ export abstract class BaseStore<T = any> extends Singleton {
this.onSync(model);
};
subscribeToBroadcast(this.syncMainChannel, callback);
this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncMainChannel, callback));
this.syncDisposers.push(subscribeToBroadcast(this.syncMainChannel, callback));
}
if (ipcRenderer) {
@ -133,8 +132,7 @@ export abstract class BaseStore<T = any> extends Singleton {
this.onSyncFromMain(model);
};
subscribeToBroadcast(this.syncRendererChannel, callback);
this.syncDisposers.push(() => unsubscribeFromBroadcast(this.syncRendererChannel, callback));
this.syncDisposers.push(subscribeToBroadcast(this.syncRendererChannel, callback));
}
}

View File

@ -21,9 +21,9 @@
import { action, computed, observable, IComputedValue, IObservableArray } from "mobx";
import type { CatalogEntity } from "./catalog-entity";
import { iter } from "../utils";
import { iter, Singleton } from "../utils";
export class CatalogEntityRegistry {
export class CatalogEntityRegistry extends Singleton {
protected sources = observable.map<string, IComputedValue<CatalogEntity[]>>([], { deep: true });
@action addObservableSource(id: string, source: IObservableArray<CatalogEntity>) {
@ -48,5 +48,3 @@ export class CatalogEntityRegistry {
return items as T[];
}
}
export const catalogEntityRegistry = new CatalogEntityRegistry();

View File

@ -19,7 +19,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { handleRequest } from "./ipc";
import { ClusterId, ClusterStore } from "./cluster-store";
import { appEventBus } from "./event-bus";
import { ResourceApplier } from "../main/resource-applier";
@ -33,13 +32,13 @@ export const clusterDisconnectHandler = "cluster:disconnect";
export const clusterKubectlApplyAllHandler = "cluster:kubectl-apply-all";
if (ipcMain) {
handleRequest(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => {
ipcMain.handle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => {
return ClusterStore.getInstance()
.getById(clusterId)
?.activate(force);
});
handleRequest(clusterSetFrameIdHandler, (event: IpcMainInvokeEvent, clusterId: ClusterId) => {
ipcMain.handle(clusterSetFrameIdHandler, (event: IpcMainInvokeEvent, clusterId: ClusterId) => {
const cluster = ClusterStore.getInstance().getById(clusterId);
if (cluster) {
@ -48,13 +47,13 @@ if (ipcMain) {
}
});
handleRequest(clusterRefreshHandler, (event, clusterId: ClusterId) => {
ipcMain.handle(clusterRefreshHandler, (event, clusterId: ClusterId) => {
return ClusterStore.getInstance()
.getById(clusterId)
?.refresh({ refreshMetadata: true });
});
handleRequest(clusterDisconnectHandler, (event, clusterId: ClusterId) => {
ipcMain.handle(clusterDisconnectHandler, (event, clusterId: ClusterId) => {
appEventBus.emit({name: "cluster", action: "stop"});
const cluster = ClusterStore.getInstance().getById(clusterId);
@ -64,7 +63,7 @@ if (ipcMain) {
}
});
handleRequest(clusterKubectlApplyAllHandler, (event, clusterId: ClusterId, resources: string[]) => {
ipcMain.handle(clusterKubectlApplyAllHandler, (event, clusterId: ClusterId, resources: string[]) => {
appEventBus.emit({name: "cluster", action: "kubectl-apply-all"});
const cluster = ClusterStore.getInstance().getById(clusterId);

View File

@ -31,7 +31,7 @@ import { appEventBus } from "./event-bus";
import { dumpConfigYaml } from "./kube-helpers";
import { saveToAppFiles } from "./utils/saveToAppFiles";
import type { KubeConfig } from "@kubernetes/client-node";
import { handleRequest, requestMain, subscribeToBroadcast, unsubscribeAllFromBroadcast } from "./ipc";
import { requestMain, subscribeToBroadcast } from "./ipc";
import type { ResourceType } from "../renderer/components/cluster-settings/components/cluster-metrics-setting";
import { disposer, noop } from "./utils";
@ -170,7 +170,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
}
});
} else if (ipcMain) {
handleRequest(ClusterStore.stateRequestChannel, (): clusterStateSync[] => {
ipcMain.handle(ClusterStore.stateRequestChannel, (): clusterStateSync[] => {
const states: clusterStateSync[] = [];
this.clustersList.forEach((cluster) => {
@ -191,7 +191,7 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
reaction(() => this.connectedClustersList, () => {
this.pushState();
}),
() => unsubscribeAllFromBroadcast("cluster:state"),
() => ipcMain.removeAllListeners("cluster:state"),
);
}
}

View File

@ -27,13 +27,10 @@ import { ipcMain, ipcRenderer, webContents, remote } from "electron";
import { toJS } from "mobx";
import logger from "../../main/logger";
import { ClusterFrameInfo, clusterFrameMap } from "../cluster-frames";
import type { Disposer } from "../utils";
const subFramesChannel = "ipc:get-sub-frames";
export function handleRequest(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) {
ipcMain.handle(channel, listener);
}
export async function requestMain(channel: string, ...args: any[]) {
return ipcRenderer.invoke(channel, ...args);
}
@ -73,34 +70,14 @@ export async function broadcastMessage(channel: string, ...args: any[]) {
}
}
export function subscribeToBroadcast(channel: string, listener: (...args: any[]) => any) {
if (ipcRenderer) {
ipcRenderer.on(channel, listener);
} else if (ipcMain) {
ipcMain.on(channel, listener);
}
export function subscribeToBroadcast(channel: string, listener: (...args: any[]) => any): Disposer {
const source: NodeJS.EventEmitter = ipcRenderer ?? ipcMain;
return listener;
}
source?.on(channel, listener);
export function unsubscribeFromBroadcast(channel: string, listener: (...args: any[]) => any) {
if (ipcRenderer) {
ipcRenderer.off(channel, listener);
} else if (ipcMain) {
ipcMain.off(channel, listener);
}
}
export function unsubscribeAllFromBroadcast(channel: string) {
if (ipcRenderer) {
ipcRenderer.removeAllListeners(channel);
} else if (ipcMain) {
ipcMain.removeAllListeners(channel);
}
return () => source?.off(channel, listener);
}
export function bindBroadcastHandlers() {
handleRequest(subFramesChannel, () => {
return getSubFrames();
});
ipcMain.handle(subFramesChannel, getSubFrames);
}

View File

@ -20,15 +20,13 @@
*/
import { CatalogEntity, catalogEntityRegistry as registry } from "../../common/catalog";
import { CatalogEntity, CatalogEntityRegistry as InternalRegistry } from "../../common/catalog";
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog/catalog-category-registry";
export * from "../../common/catalog-entities";
export class CatalogEntityRegistry {
getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] {
return registry.getItemsForApiKind<T>(apiVersion, kind);
static getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] {
return InternalRegistry.getInstance().getItemsForApiKind<T>(apiVersion, kind);
}
}
export const catalogEntities = new CatalogEntityRegistry();

View File

@ -20,13 +20,13 @@
*/
import { watch } from "chokidar";
import { ipcRenderer } from "electron";
import { ipcMain, ipcRenderer } from "electron";
import { EventEmitter } from "events";
import fse from "fs-extra";
import { observable, reaction, toJS, when } from "mobx";
import os from "os";
import path from "path";
import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc";
import { broadcastMessage, requestMain, subscribeToBroadcast } from "../common/ipc";
import { Singleton } from "../common/utils";
import logger from "../main/logger";
import { ExtensionInstallationStateStore } from "../renderer/components/+extensions/extension-install.store";
@ -136,7 +136,7 @@ export class ExtensionDiscovery extends Singleton {
}
async initMain() {
handleRequest(ExtensionDiscovery.extensionDiscoveryChannel, () => this.toJSON());
ipcMain.handle(ExtensionDiscovery.extensionDiscoveryChannel, () => this.toJSON());
reaction(() => this.toJSON(), () => {
this.broadcast();

View File

@ -19,13 +19,13 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { app, ipcRenderer, remote } from "electron";
import { app, ipcMain, ipcRenderer, remote } from "electron";
import { EventEmitter } from "events";
import { isEqual } from "lodash";
import { action, computed, observable, reaction, toJS, when } from "mobx";
import path from "path";
import { getHostedCluster } from "../common/cluster-store";
import { broadcastMessage, handleRequest, requestMain, subscribeToBroadcast } from "../common/ipc";
import { broadcastMessage, requestMain, subscribeToBroadcast } from "../common/ipc";
import { Singleton } from "../common/utils";
import logger from "../main/logger";
import type { InstalledExtension } from "./extension-discovery";
@ -164,7 +164,7 @@ export class ExtensionLoader extends Singleton {
this.broadcastExtensions();
});
handleRequest(ExtensionLoader.extensionsMainChannel, () => {
ipcMain.handle(ExtensionLoader.extensionsMainChannel, () => {
return Array.from(this.toJSON());
});

View File

@ -23,7 +23,7 @@ import type { MenuRegistration } from "./registries/menu-registry";
import { LensExtension } from "./lens-extension";
import { WindowManager } from "../main/window-manager";
import { getExtensionPageUrl } from "./registries/page-registry";
import { CatalogEntity, catalogEntityRegistry } from "../common/catalog";
import { CatalogEntity, CatalogEntityRegistry } from "../common/catalog";
import type { IObservableArray } from "mobx";
export class LensMainExtension extends LensExtension {
@ -41,10 +41,10 @@ export class LensMainExtension extends LensExtension {
}
addCatalogSource(id: string, source: IObservableArray<CatalogEntity>) {
catalogEntityRegistry.addObservableSource(`${this.name}:${id}`, source);
CatalogEntityRegistry.getInstance().addObservableSource(`${this.name}:${id}`, source);
}
removeCatalogSource(id: string) {
catalogEntityRegistry.removeSource(`${this.name}:${id}`);
CatalogEntityRegistry.getInstance().removeSource(`${this.name}:${id}`);
}
}

View File

@ -20,33 +20,19 @@
*/
import { reaction, toJS } from "mobx";
import { broadcastMessage, subscribeToBroadcast, unsubscribeFromBroadcast } from "../common/ipc";
import type { CatalogEntityRegistry} from "../common/catalog";
import "../common/catalog-entities/kubernetes-cluster";
import type { Disposer } from "../common/utils";
import { broadcastMessage, subscribeToBroadcast } from "../common/ipc";
import { CatalogEntityRegistry} from "../common/catalog";
import { disposer, Disposer } from "../common/utils";
export class CatalogPusher {
static init(catalog: CatalogEntityRegistry) {
new CatalogPusher(catalog).init();
}
private constructor(private catalog: CatalogEntityRegistry) {}
init() {
const disposers: Disposer[] = [];
disposers.push(reaction(() => toJS(this.catalog.items, { recurseEverything: true }), (items) => {
export function pushCatalogToRenderer(): Disposer {
return disposer(
reaction(() => toJS(CatalogEntityRegistry.getInstance().items, { recurseEverything: true }), (items) => {
broadcastMessage("catalog:items", items);
}, {
fireImmediately: true,
}));
const listener = subscribeToBroadcast("catalog:broadcast", () => {
broadcastMessage("catalog:items", toJS(this.catalog.items, { recurseEverything: true }));
});
disposers.push(() => unsubscribeFromBroadcast("catalog:broadcast", listener));
return disposers;
}
}),
subscribeToBroadcast("catalog:broadcast", () => {
broadcastMessage("catalog:items", toJS(CatalogEntityRegistry.getInstance().items, { recurseEverything: true }));
})
);
}

View File

@ -20,7 +20,7 @@
*/
import { action, observable, IComputedValue, computed, ObservableMap, runInAction } from "mobx";
import { CatalogEntity, catalogEntityRegistry } from "../../common/catalog";
import { CatalogEntity, CatalogEntityRegistry } from "../../common/catalog";
import { watch } from "chokidar";
import fs from "fs";
import fse from "fs-extra";
@ -54,7 +54,7 @@ export class KubeconfigSyncManager extends Singleton {
logger.info(`${logPrefix} starting requested syncs`);
catalogEntityRegistry.addComputedSource(KubeconfigSyncManager.syncName, computed(() => (
CatalogEntityRegistry.getInstance().addComputedSource(KubeconfigSyncManager.syncName, computed(() => (
Array.from(iter.flatMap(
this.sources.values(),
([entities]) => entities.get()
@ -88,7 +88,7 @@ export class KubeconfigSyncManager extends Singleton {
this.stopOldSync(filePath);
}
catalogEntityRegistry.removeSource(KubeconfigSyncManager.syncName);
CatalogEntityRegistry.getInstance().removeSource(KubeconfigSyncManager.syncName);
this.syncing = false;
}

View File

@ -28,7 +28,7 @@ import type { Cluster } from "./cluster";
import logger from "./logger";
import { apiKubePrefix } from "../common/vars";
import { Singleton } from "../common/utils";
import { catalogEntityRegistry } from "../common/catalog";
import { CatalogEntityRegistry } from "../common/catalog";
import { KubernetesCluster } from "../common/catalog-entities/kubernetes-cluster";
export class ClusterManager extends Singleton {
@ -39,7 +39,7 @@ export class ClusterManager extends Singleton {
this.updateCatalog(ClusterStore.getInstance().clustersList);
}, { fireImmediately: true });
reaction(() => catalogEntityRegistry.getItemsForApiKind<KubernetesCluster>("entity.k8slens.dev/v1alpha1", "KubernetesCluster"), (entities) => {
reaction(() => CatalogEntityRegistry.getInstance().getItemsForApiKind<KubernetesCluster>("entity.k8slens.dev/v1alpha1", "KubernetesCluster"), (entities) => {
this.syncClustersFromCatalog(entities);
});
@ -64,11 +64,13 @@ export class ClusterManager extends Singleton {
}
@action protected updateCatalog(clusters: Cluster[]) {
const registry = CatalogEntityRegistry.getInstance();
for (const cluster of clusters) {
const index = catalogEntityRegistry.items.findIndex((entity) => entity.metadata.uid === cluster.id);
const index = registry.items.findIndex((entity) => entity.metadata.uid === cluster.id);
if (index !== -1) {
const entity = catalogEntityRegistry.items[index];
const entity = registry.items[index];
entity.status.phase = cluster.disconnected ? "disconnected" : "connected";
entity.status.active = !cluster.disconnected;
@ -76,7 +78,7 @@ export class ClusterManager extends Singleton {
if (cluster.preferences?.clusterName) {
entity.metadata.name = cluster.preferences.clusterName;
}
catalogEntityRegistry.items.splice(index, 1, entity);
registry.items.splice(index, 1, entity);
}
}
}

View File

@ -45,19 +45,20 @@ import type { LensExtensionId } from "../extensions/lens-extension";
import { FilesystemProvisionerStore } from "./extension-filesystem";
import { installDeveloperTools } from "./developer-tools";
import { LensProtocolRouterMain } from "./protocol-handler";
import { getAppVersion, getAppVersionFromProxyServer } from "../common/utils";
import { disposer, getAppVersion, getAppVersionFromProxyServer } from "../common/utils";
import { bindBroadcastHandlers } from "../common/ipc";
import { startUpdateChecking } from "./app-updater";
import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
import { CatalogPusher } from "./catalog-pusher";
import { catalogEntityRegistry } from "../common/catalog";
import { pushCatalogToRenderer } from "./catalog-pusher";
import { HotbarStore } from "../common/hotbar-store";
import { HelmRepoManager } from "./helm/helm-repo-manager";
import { KubeconfigSyncManager } from "./catalog-sources";
import { handleWsUpgrade } from "./proxy/ws-upgrade";
import { initRegistries } from "./initializers";
import { CatalogEntityRegistry } from "../common/catalog";
const workingDir = path.join(app.getPath("appData"), appName);
const cleanup = disposer();
app.setName(appName);
@ -110,6 +111,8 @@ app.on("second-instance", (event, argv) => {
});
app.on("ready", async () => {
CatalogEntityRegistry.createInstance();
logger.info(`🚀 Starting ${productName} from "${workingDir}"`);
logger.info("🐚 Syncing shell environment");
await shellSync();
@ -143,7 +146,6 @@ app.on("ready", async () => {
const lensProxy = LensProxy.createInstance(handleWsUpgrade);
ClusterManager.createInstance();
KubeconfigSyncManager.createInstance().startSync();
try {
logger.info("🔌 Starting LensProxy");
@ -189,17 +191,14 @@ app.on("ready", async () => {
}
ipcMain.on(IpcRendererNavigationEvents.LOADED, () => {
CatalogPusher.init(catalogEntityRegistry);
KubeconfigSyncManager.createInstance().startSync();
cleanup.push(pushCatalogToRenderer());
startUpdateChecking();
LensProtocolRouterMain
.getInstance()
.rendererLoaded = true;
LensProtocolRouterMain.getInstance().rendererLoaded = true;
});
ExtensionLoader.getInstance().whenLoaded.then(() => {
LensProtocolRouterMain
.getInstance()
.extensionsLoaded = true;
LensProtocolRouterMain.getInstance().extensionsLoaded = true;
});
logger.info("🧩 Initializing extensions");
@ -253,6 +252,7 @@ app.on("will-quit", (event) => {
appEventBus.emit({name: "app", action: "close"});
ClusterManager.getInstance(false)?.stop(); // close cluster connections
KubeconfigSyncManager.getInstance(false)?.stopSync();
cleanup();
if (blockQuit) {
event.preventDefault(); // prevent app's default shutdown (e.g. required for telemetry, etc.)

View File

@ -44,6 +44,7 @@ import { HelmRepoManager } from "../main/helm/helm-repo-manager";
import { ExtensionInstallationStateStore } from "./components/+extensions/extension-install.store";
import { DefaultProps } from "./mui-base-theme";
import { initCommandRegistry, initEntitySettingsRegistry, initKubeObjectMenuRegistry, initRegistries, initWelcomeMenuRegistry, intiKubeObjectDetailRegistry } from "./initializers";
import { CatalogEntityRegistry } from "../common/catalog";
/**
* If this is a development buid, wait a second to attach
@ -75,6 +76,8 @@ export async function bootstrap(App: AppComponent) {
await attachChromeDebugger();
rootElem.classList.toggle("is-mac", isMac);
CatalogEntityRegistry.createInstance();
initRegistries();
initCommandRegistry();
initEntitySettingsRegistry();