From 70bbb9fa62e17acfd9767c673a2ddcd26de0725d Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 21 Jul 2020 12:54:45 +0300 Subject: [PATCH] cluster-ipc refactoring Signed-off-by: Roman --- src/common/cluster-ipc.ts | 32 +++++++++++++++++++ src/common/ipc.ts | 22 +++++++++++-- src/main/cluster-manager.ts | 31 +++--------------- src/main/cluster.ts | 10 ++---- src/renderer/components/+cluster/cluster.tsx | 6 +++- src/renderer/components/app.tsx | 2 +- .../cluster-manager/cluster-manager.tsx | 17 ++++------ .../cluster-manager/cluster-status.tsx | 5 ++- src/renderer/config.store.ts | 2 +- src/renderer/index.tsx | 2 +- 10 files changed, 76 insertions(+), 53 deletions(-) create mode 100644 src/common/cluster-ipc.ts diff --git a/src/common/cluster-ipc.ts b/src/common/cluster-ipc.ts new file mode 100644 index 0000000000..416802d537 --- /dev/null +++ b/src/common/cluster-ipc.ts @@ -0,0 +1,32 @@ +import { createIpcChannel } from "./ipc"; +import { ClusterId, clusterStore } from "./cluster-store"; +import { tracker } from "./tracker"; + +export const clusterIpc = { + refresh: createIpcChannel({ + channel: "cluster:refresh", + handle: async (clusterId: ClusterId = clusterStore.activeClusterId) => { + const cluster = clusterStore.getById(clusterId); + if (cluster) { + await cluster.refreshStatus(); + cluster.pushState(); + } + }, + }), + + disconnect: createIpcChannel({ + channel: "cluster:disconnect", + handle: (clusterId: ClusterId) => { + tracker.event("cluster", "stop"); + clusterStore.getById(clusterId)?.disconnect(); + }, + }), + + reconnect: createIpcChannel({ + channel: "cluster:reconnect", + handle: (clusterId: ClusterId) => { + tracker.event("cluster", "reconnect"); + clusterStore.getById(clusterId)?.reconnect(); + }, + }), +} \ No newline at end of file diff --git a/src/common/ipc.ts b/src/common/ipc.ts index bdcce8eee3..96a0157358 100644 --- a/src/common/ipc.ts +++ b/src/common/ipc.ts @@ -43,9 +43,9 @@ export async function invokeIpc(channel: IpcChannel, ...args: any[]): P } // todo: make isomorphic api -export function handleIpc(channel: IpcChannel, handler: IpcMessageHandler, options: IpcHandleOpts = {}) { +export function handleIpc(channel: IpcChannel, handler: IpcMessageHandler, options: IpcHandleOpts = {}) { const { timeout = 0 } = options; - ipcMain.handle(channel, async (event, ...args: T) => { + ipcMain.handle(channel, async (event, ...args) => { logger.info(`[IPC]: handle "${channel}"`, { args }); return new Promise(async (resolve, reject) => { let timerId; @@ -65,3 +65,21 @@ export function handleIpc(channel: IpcChannel, handler: IpcMess }) }) } + +export interface IpcPairOptions { + channel: IpcChannel + handle?: IpcMessageHandler + options?: IpcHandleOpts +} + +export function createIpcChannel({ channel, ...initOpts }: IpcPairOptions) { + return { + handleInMain: (opts: Partial> = {}) => { + const { handle = initOpts.handle, options = initOpts.options } = opts; + return handleIpc(channel, handle, options); + }, + invokeFromRenderer: (...args: any[]) => { + return invokeIpc(channel, ...args); + }, + } +} diff --git a/src/main/cluster-manager.ts b/src/main/cluster-manager.ts index a4e8057bef..7ac8d2e520 100644 --- a/src/main/cluster-manager.ts +++ b/src/main/cluster-manager.ts @@ -2,10 +2,9 @@ import type http from "http" import { autorun, reaction } from "mobx"; import { apiKubePrefix } from "../common/vars"; import { ClusterId, clusterStore } from "../common/cluster-store" -import { handleIpc } from "../common/ipc"; -import { Cluster, ClusterIpcChannel } from "./cluster" +import { Cluster } from "./cluster" +import { clusterIpc } from "../common/cluster-ipc"; import logger from "./logger"; -import { tracker } from "../common/tracker"; export class ClusterManager { protected activeClusterId: ClusterId; @@ -53,9 +52,9 @@ export class ClusterManager { }); // listen for ipc-events that must/can be handled *only* in main-process (nodeIntegration=true) - handleIpc(ClusterIpcChannel.INIT, this.onClusterInit); - handleIpc(ClusterIpcChannel.DISCONNECT, this.onClusterDisconnect); - handleIpc(ClusterIpcChannel.RECONNECT, this.onClusterReconnect); + clusterIpc.refresh.handleInMain(); + clusterIpc.disconnect.handleInMain(); + clusterIpc.reconnect.handleInMain(); } stop() { @@ -64,26 +63,6 @@ export class ClusterManager { }) } - protected onClusterInit = async (id = clusterStore.activeClusterId) => { - const cluster = this.getCluster(id); - if (cluster) { - logger.info(`[CLUSTER-MANAGER]: init cluster`, cluster.getMeta()); - tracker.event("cluster", "activate"); - await cluster.refreshStatus(); - cluster.pushState(); - } - } - - protected onClusterDisconnect = (id: ClusterId) => { - tracker.event("cluster", "stop"); - this.getCluster(id)?.disconnect(); - } - - protected onClusterReconnect = (id: ClusterId) => { - tracker.event("cluster", "reconnect"); - this.getCluster(id)?.reconnect(); - } - protected getCluster(id: ClusterId) { return clusterStore.getById(id); } diff --git a/src/main/cluster.ts b/src/main/cluster.ts index be4417242e..1edeb41ee2 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -13,12 +13,6 @@ import { getFeatures, installFeature, uninstallFeature, upgradeFeature } from ". import request, { RequestPromiseOptions } from "request-promise-native" import logger from "./logger" -export enum ClusterIpcChannel { - INIT = "cluster:init", - DISCONNECT = "cluster:disconnect", - RECONNECT = "cluster:reconnect", -} - export enum ClusterStatus { AccessGranted = 2, AccessDenied = 1, @@ -341,7 +335,7 @@ export class Cluster implements ClusterModel { } pushState = (clusterState = this.getState()) => { - logger.info(`[CLUSTER]: push-state`, clusterState); + logger.debug(`[CLUSTER]: push-state`, clusterState); broadcastIpc({ // webContentId: viewId, // todo: send to cluster-view only channel: "cluster:state", @@ -354,6 +348,8 @@ export class Cluster implements ClusterModel { return { id: this.id, name: this.contextName, + initialized: this.initialized, + accessible: this.accessible, } } } diff --git a/src/renderer/components/+cluster/cluster.tsx b/src/renderer/components/+cluster/cluster.tsx index 13df2cad0a..940e10e7ad 100644 --- a/src/renderer/components/+cluster/cluster.tsx +++ b/src/renderer/components/+cluster/cluster.tsx @@ -1,7 +1,7 @@ import "./cluster.scss" import React from "react"; -import { computed, reaction } from "mobx"; +import { computed, reaction, when } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { MainLayout } from "../layout/main-layout"; import { ClusterIssues } from "./cluster-issues"; @@ -13,6 +13,7 @@ import { nodesStore } from "../+nodes/nodes.store"; import { podsStore } from "../+workloads-pods/pods.store"; import { clusterStore } from "./cluster.store"; import { eventStore } from "../+events/event.store"; +import { configStore } from "../../config.store"; import { isAllowedResource } from "../../api/rbac"; @observer @@ -24,7 +25,10 @@ export class Cluster extends React.Component { private dependentStores = [nodesStore, podsStore]; + // todo: refactor async componentDidMount() { + await when(() => configStore.isLoaded); + const { dependentStores } = this; if (!isAllowedResource("nodes")) { dependentStores.splice(dependentStores.indexOf(nodesStore), 1) diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx index 8992ea6fe2..94b978c623 100755 --- a/src/renderer/components/app.tsx +++ b/src/renderer/components/app.tsx @@ -2,7 +2,6 @@ import "./app.scss"; import React from "react"; import { observer } from "mobx-react"; import { i18nStore } from "../i18n"; -import { configStore } from "../config.store"; import { Terminal } from "./dock/terminal"; import { Redirect, Route, Switch } from "react-router"; import { Notifications } from "./notifications"; @@ -35,6 +34,7 @@ import { clusterStore } from "../../common/cluster-store"; import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings"; import { Workspaces, workspacesRoute } from "./+workspaces"; import { ErrorBoundary } from "./error-boundary"; +import { configStore } from "../config.store"; @observer export class App extends React.Component { diff --git a/src/renderer/components/cluster-manager/cluster-manager.tsx b/src/renderer/components/cluster-manager/cluster-manager.tsx index 09e89dc3a2..063de4f1c4 100644 --- a/src/renderer/components/cluster-manager/cluster-manager.tsx +++ b/src/renderer/components/cluster-manager/cluster-manager.tsx @@ -1,15 +1,14 @@ import "./cluster-manager.scss" import React from "react"; import { observer } from "mobx-react"; -import { computed, observable } from "mobx"; +import { observable } from "mobx"; import { App } from "../app"; import { ClusterStatus } from "./cluster-status"; import { ClustersMenu } from "./clusters-menu"; import { BottomBar } from "./bottom-bar"; import { cssNames, IClassName } from "../../utils"; -import { invokeIpc } from "../../../common/ipc"; -import { ClusterIpcChannel } from "../../../main/cluster"; import { clusterStore } from "../../../common/cluster-store"; +import { clusterIpc } from "../../../common/cluster-ipc"; interface Props { className?: IClassName; @@ -18,21 +17,17 @@ interface Props { @observer export class ClusterManager extends React.Component { - @observable appReady = false; - - @computed get clusterReady() { - return clusterStore.activeCluster?.isReady - } + @observable isReady = false; async componentDidMount() { - invokeIpc(ClusterIpcChannel.INIT); + clusterIpc.refresh.invokeFromRenderer(); await App.init(); - this.appReady = true; + this.isReady = true; } render() { const { className, contentClass } = this.props; - const isReady = this.appReady && this.clusterReady; + const isReady = this.isReady && clusterStore.activeCluster?.isReady; return (
diff --git a/src/renderer/components/cluster-manager/cluster-status.tsx b/src/renderer/components/cluster-manager/cluster-status.tsx index d1d5239f4c..f305210f2b 100644 --- a/src/renderer/components/cluster-manager/cluster-status.tsx +++ b/src/renderer/components/cluster-manager/cluster-status.tsx @@ -1,8 +1,6 @@ import "./cluster-status.scss" import React from "react"; import type { KubeAuthProxyResponse } from "../../../main/kube-auth-proxy"; -import { ClusterIpcChannel } from "../../../main/cluster"; -import { invokeIpc } from "../../../common/ipc"; import { clusterStore } from "../../../common/cluster-store"; import { ipcRenderer } from "electron"; import { observable } from "mobx"; @@ -10,6 +8,7 @@ import { observer } from "mobx-react"; import { Icon } from "../icon"; import { Button } from "../button"; import { cssNames } from "../../utils"; +import { clusterIpc } from "../../../common/cluster-ipc"; @observer export class ClusterStatus extends React.Component { @@ -36,7 +35,7 @@ export class ClusterStatus extends React.Component { reconnect = () => { this.authOutput = ["Reconnecting ...\n"]; - invokeIpc(ClusterIpcChannel.RECONNECT, this.clusterId); + clusterIpc.reconnect.invokeFromRenderer(this.clusterId); } render() { diff --git a/src/renderer/config.store.ts b/src/renderer/config.store.ts index 54b45d2622..ffc21c25d7 100755 --- a/src/renderer/config.store.ts +++ b/src/renderer/config.store.ts @@ -3,7 +3,7 @@ import { observable, when } from "mobx"; import { autobind, interval } from "./utils"; import { apiBase } from "./api"; -// todo: use user-store.ts as isomorphic-store with config/settings for ui +// todo: remove, merge with common/user-store.ts @autobind() export class ConfigStore { diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx index 38486fd368..d1631782bb 100644 --- a/src/renderer/index.tsx +++ b/src/renderer/index.tsx @@ -24,7 +24,7 @@ class LensApp extends React.Component { userStore.load(), workspaceStore.load(), clusterStore.load(), - ]); + ]) render(, rootElem); }