mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix iframe ipc flakyness after cluster is removed (#954)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
386e7c63bb
commit
11ea9d2098
@ -93,6 +93,10 @@ export class BaseStore<T = any> extends Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
unregisterIpcListener() {
|
||||
ipcRenderer.removeAllListeners(this.syncChannel)
|
||||
}
|
||||
|
||||
disableSync() {
|
||||
this.syncDisposers.forEach(dispose => dispose());
|
||||
this.syncDisposers.length = 0;
|
||||
|
||||
@ -9,7 +9,7 @@ export const clusterIpc = {
|
||||
const cluster = clusterStore.getById(clusterId);
|
||||
if (cluster) {
|
||||
if (frameId) cluster.frameId = frameId; // save cluster's webFrame.routingId to be able to send push-updates
|
||||
return cluster.activate(true);
|
||||
return cluster.activate();
|
||||
}
|
||||
},
|
||||
}),
|
||||
@ -58,4 +58,4 @@ export const clusterIpc = {
|
||||
return clusterStore.getById(clusterId)?.upgradeFeature(feature, config)
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import path from "path";
|
||||
import { app, ipcRenderer, remote } from "electron";
|
||||
import { app, ipcRenderer, remote, webFrame, webContents } from "electron";
|
||||
import { unlink } from "fs-extra";
|
||||
import { action, computed, observable, toJS } from "mobx";
|
||||
import { BaseStore } from "./base-store";
|
||||
@ -73,20 +73,27 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
accessPropertiesByDotNotation: false, // To make dots safe in cluster context names
|
||||
migrations: migrations,
|
||||
});
|
||||
if (ipcRenderer) {
|
||||
ipcRenderer.on("cluster:state", (event, model: ClusterState) => {
|
||||
this.applyWithoutSync(() => {
|
||||
logger.silly(`[CLUSTER-STORE]: received push-state at ${location.host}`, model);
|
||||
this.getById(model.id)?.updateModel(model);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@observable activeClusterId: ClusterId;
|
||||
@observable removedClusters = observable.map<ClusterId, Cluster>();
|
||||
@observable clusters = observable.map<ClusterId, Cluster>();
|
||||
|
||||
registerIpcListener() {
|
||||
logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`)
|
||||
ipcRenderer.on("cluster:state", (event, model: ClusterState) => {
|
||||
this.applyWithoutSync(() => {
|
||||
logger.silly(`[CLUSTER-STORE]: received push-state at ${location.host} (${webFrame.routingId})`, model);
|
||||
this.getById(model.id)?.updateModel(model);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
unregisterIpcListener() {
|
||||
super.unregisterIpcListener()
|
||||
ipcRenderer.removeAllListeners("cluster:state")
|
||||
}
|
||||
|
||||
@computed get activeCluster(): Cluster | null {
|
||||
return this.getById(this.activeClusterId);
|
||||
}
|
||||
|
||||
@ -56,10 +56,10 @@ export class Cluster implements ClusterModel {
|
||||
@observable kubeConfigPath: string;
|
||||
@observable apiUrl: string; // cluster server url
|
||||
@observable kubeProxyUrl: string; // lens-proxy to kube-api url
|
||||
@observable online: boolean;
|
||||
@observable accessible: boolean;
|
||||
@observable ready: boolean;
|
||||
@observable disconnected: boolean;
|
||||
@observable online = false;
|
||||
@observable accessible = false;
|
||||
@observable ready = false;
|
||||
@observable disconnected = true;
|
||||
@observable failureReason: string;
|
||||
@observable nodes = 0;
|
||||
@observable version: string;
|
||||
@ -124,13 +124,14 @@ export class Cluster implements ClusterModel {
|
||||
this.eventDisposers.length = 0;
|
||||
}
|
||||
|
||||
async activate(init = false) {
|
||||
@action
|
||||
async activate() {
|
||||
logger.info(`[CLUSTER]: activate`, this.getMeta());
|
||||
await this.whenInitialized;
|
||||
if (!this.eventDisposers.length) {
|
||||
this.bindEvents();
|
||||
}
|
||||
if (this.disconnected || (!init && !this.accessible)) {
|
||||
if (this.disconnected || !this.accessible) {
|
||||
await this.reconnect();
|
||||
}
|
||||
await this.refreshConnectionStatus()
|
||||
@ -143,6 +144,7 @@ export class Cluster implements ClusterModel {
|
||||
return this.pushState();
|
||||
}
|
||||
|
||||
@action
|
||||
async reconnect() {
|
||||
logger.info(`[CLUSTER]: reconnect`, this.getMeta());
|
||||
this.contextHandler.stopServer();
|
||||
|
||||
@ -134,7 +134,6 @@ export class LensProxy {
|
||||
protected async handleRequest(proxy: httpProxy, req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
const cluster = this.clusterManager.getClusterForRequest(req)
|
||||
if (cluster) {
|
||||
await cluster.contextHandler.ensureServer();
|
||||
const proxyTarget = await this.getProxyTarget(req, cluster.contextHandler)
|
||||
if (proxyTarget) {
|
||||
// allow to fetch apis in "clusterId.localhost:port" from "localhost:port"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import "./components/app.scss"
|
||||
import React from "react";
|
||||
import { render } from "react-dom";
|
||||
import { render, unmountComponentAtNode } from "react-dom";
|
||||
import { isMac } from "../common/vars";
|
||||
import { userStore } from "../common/user-store";
|
||||
import { workspaceStore } from "../common/workspace-store";
|
||||
@ -27,10 +27,22 @@ export async function bootstrap(App: AppComponent) {
|
||||
themeStore.init(),
|
||||
]);
|
||||
|
||||
// Register additional store listeners
|
||||
clusterStore.registerIpcListener();
|
||||
|
||||
// init app's dependencies if any
|
||||
if (App.init) {
|
||||
await App.init();
|
||||
}
|
||||
window.addEventListener("message", (ev: MessageEvent) => {
|
||||
if (ev.data === "teardown") {
|
||||
userStore.unregisterIpcListener()
|
||||
workspaceStore.unregisterIpcListener()
|
||||
clusterStore.unregisterIpcListener()
|
||||
unmountComponentAtNode(rootElem)
|
||||
window.location.href = "about:blank"
|
||||
}
|
||||
})
|
||||
render(<>
|
||||
{isMac && <div id="draggable-top" />}
|
||||
<App />
|
||||
|
||||
@ -19,8 +19,11 @@ export async function initView(clusterId: ClusterId) {
|
||||
if (!clusterId || lensViews.has(clusterId)) {
|
||||
return;
|
||||
}
|
||||
logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`)
|
||||
const cluster = clusterStore.getById(clusterId);
|
||||
if (!cluster) {
|
||||
return;
|
||||
}
|
||||
logger.info(`[LENS-VIEW]: init dashboard, clusterId=${clusterId}`)
|
||||
const parentElem = document.getElementById("lens-views");
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.name = cluster.contextName;
|
||||
@ -42,9 +45,9 @@ export async function autoCleanOnRemove(clusterId: ClusterId, iframe: HTMLIFrame
|
||||
// Keep frame in DOM to avoid possible bugs when same cluster re-created after being removed.
|
||||
// In that case for some reasons `webFrame.routingId` returns some previous frameId (usage in app.tsx)
|
||||
// Issue: https://github.com/lensapp/lens/issues/811
|
||||
iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}`;
|
||||
iframe.removeAttribute("src")
|
||||
iframe.dataset.meta = `${iframe.name} was removed at ${new Date().toLocaleString()}`
|
||||
iframe.removeAttribute("name")
|
||||
iframe.contentWindow.postMessage("teardown", "*")
|
||||
}
|
||||
|
||||
export function refreshViews() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user