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

Fix UI staleness after network issues (#1192)

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2020-11-02 14:51:04 +02:00 committed by GitHub
parent 32ca885596
commit c7f77a01f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 14 deletions

View File

@ -1,5 +1,6 @@
import "../common/cluster-ipc"; import "../common/cluster-ipc";
import type http from "http" import type http from "http"
import { ipcMain } from "electron"
import { autorun } from "mobx"; import { autorun } from "mobx";
import { clusterStore, getClusterIdFromHost } from "../common/cluster-store" import { clusterStore, getClusterIdFromHost } from "../common/cluster-store"
import { Cluster } from "./cluster" import { Cluster } from "./cluster"
@ -30,6 +31,29 @@ export class ClusterManager {
}, { }, {
delay: 250 delay: 250
}); });
ipcMain.on("network:offline", () => { this.onNetworkOffline() })
ipcMain.on("network:online", () => { this.onNetworkOnline() })
}
protected onNetworkOffline() {
logger.info("[CLUSTER-MANAGER]: network is offline")
clusterStore.enabledClustersList.forEach((cluster) => {
if (!cluster.disconnected) {
cluster.online = false
cluster.accessible = false
cluster.refreshConnectionStatus().catch((e) => e)
}
})
}
protected onNetworkOnline() {
logger.info("[CLUSTER-MANAGER]: network is online")
clusterStore.enabledClustersList.forEach((cluster) => {
if (!cluster.disconnected) {
cluster.refreshConnectionStatus().catch((e) => e)
}
})
} }
stop() { stop() {

View File

@ -67,12 +67,12 @@ export class Cluster implements ClusterModel, ClusterState {
@observable kubeConfigPath: string; @observable kubeConfigPath: string;
@observable apiUrl: string; // cluster server url @observable apiUrl: string; // cluster server url
@observable kubeProxyUrl: string; // lens-proxy to kube-api url @observable kubeProxyUrl: string; // lens-proxy to kube-api url
@observable enabled = false; @observable enabled = false; // only enabled clusters are visible to users
@observable online = false; @observable online = false; // describes if we can detect that cluster is online
@observable accessible = false; @observable accessible = false; // if user is able to access cluster resources
@observable ready = false; @observable ready = false; // cluster is in usable state
@observable reconnecting = false; @observable reconnecting = false;
@observable disconnected = true; @observable disconnected = true; // false if user has selected to connect
@observable failureReason: string; @observable failureReason: string;
@observable isAdmin = false; @observable isAdmin = false;
@observable eventCount = 0; @observable eventCount = 0;
@ -127,16 +127,16 @@ export class Cluster implements ClusterModel, ClusterState {
} }
protected bindEvents() { protected bindEvents() {
logger.info(`[CLUSTER]: bind events`, this.getMeta()); logger.info(`[CLUSTER]: bind events`, this.getMeta())
const refreshTimer = setInterval(() => !this.disconnected && this.refresh(), 30000); // every 30s const refreshTimer = setInterval(() => !this.disconnected && this.refresh(), 30000) // every 30s
const refreshMetadataTimer = setInterval(() => !this.disconnected && this.refreshMetadata(), 900000); // every 15 minutes const refreshMetadataTimer = setInterval(() => !this.disconnected && this.refreshMetadata(), 900000) // every 15 minutes
if (ipcMain) { if (ipcMain) {
this.eventDisposers.push( this.eventDisposers.push(
reaction(() => this.getState(), () => this.pushState()), reaction(() => this.getState(), () => this.pushState()),
() => { () => {
clearInterval(refreshTimer); clearInterval(refreshTimer)
clearInterval(refreshMetadataTimer); clearInterval(refreshMetadataTimer)
}, },
); );
} }

View File

@ -109,17 +109,22 @@ export class KubeWatchApi {
} }
} }
protected async onRouteEvent({ type, url }: IKubeWatchRouteEvent) { protected async onRouteEvent(event: IKubeWatchRouteEvent) {
if (type === "STREAM_END") { if (event.type === "STREAM_END") {
this.disconnect(); this.disconnect();
const { apiBase, namespace } = KubeApi.parseApi(url); const { apiBase, namespace } = KubeApi.parseApi(event.url);
const api = apiManager.getApi(apiBase); const api = apiManager.getApi(apiBase);
if (api) { if (api) {
try { try {
await api.refreshResourceVersion({ namespace }); await api.refreshResourceVersion({ namespace });
this.reconnect(); this.reconnect();
} catch (error) { } catch (error) {
console.debug("failed to refresh resource version", error) console.error("failed to refresh resource version", error)
if (this.subscribers.size > 0) {
setTimeout(() => {
this.onRouteEvent(event)
}, 1000)
}
} }
} }
} }

View File

@ -54,6 +54,9 @@ export class App extends React.Component {
appEventBus.emit({name: "cluster", action: "open", params: { appEventBus.emit({name: "cluster", action: "open", params: {
clusterId: clusterId clusterId: clusterId
}}) }})
window.addEventListener("online", () => {
window.location.reload()
})
} }
get startURL() { get startURL() {

View File

@ -1,5 +1,6 @@
import "../common/system-ca" import "../common/system-ca"
import React from "react"; import React from "react";
import { ipcRenderer } from "electron";
import { Route, Router, Switch } from "react-router"; import { Route, Router, Switch } from "react-router";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { userStore } from "../common/user-store"; import { userStore } from "../common/user-store";
@ -17,6 +18,12 @@ import { extensionLoader } from "../extensions/extension-loader";
export class LensApp extends React.Component { export class LensApp extends React.Component {
static async init() { static async init() {
extensionLoader.loadOnClusterManagerRenderer(); extensionLoader.loadOnClusterManagerRenderer();
window.addEventListener("offline", () => {
ipcRenderer.send("network:offline")
})
window.addEventListener("online", () => {
ipcRenderer.send("network:online")
})
} }
render() { render() {