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

cluster-ipc refactoring

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-07-21 12:54:45 +03:00
parent c0c1c227ca
commit 70bbb9fa62
10 changed files with 76 additions and 53 deletions

32
src/common/cluster-ipc.ts Normal file
View File

@ -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();
},
}),
}

View File

@ -43,9 +43,9 @@ export async function invokeIpc<R = any>(channel: IpcChannel, ...args: any[]): P
} }
// todo: make isomorphic api // todo: make isomorphic api
export function handleIpc<T extends any[]>(channel: IpcChannel, handler: IpcMessageHandler<T>, options: IpcHandleOpts = {}) { export function handleIpc(channel: IpcChannel, handler: IpcMessageHandler, options: IpcHandleOpts = {}) {
const { timeout = 0 } = options; const { timeout = 0 } = options;
ipcMain.handle(channel, async (event, ...args: T) => { ipcMain.handle(channel, async (event, ...args) => {
logger.info(`[IPC]: handle "${channel}"`, { args }); logger.info(`[IPC]: handle "${channel}"`, { args });
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
let timerId; let timerId;
@ -65,3 +65,21 @@ export function handleIpc<T extends any[]>(channel: IpcChannel, handler: IpcMess
}) })
}) })
} }
export interface IpcPairOptions {
channel: IpcChannel
handle?: IpcMessageHandler
options?: IpcHandleOpts
}
export function createIpcChannel({ channel, ...initOpts }: IpcPairOptions) {
return {
handleInMain: (opts: Partial<Omit<IpcPairOptions, "channel">> = {}) => {
const { handle = initOpts.handle, options = initOpts.options } = opts;
return handleIpc(channel, handle, options);
},
invokeFromRenderer: (...args: any[]) => {
return invokeIpc(channel, ...args);
},
}
}

View File

@ -2,10 +2,9 @@ import type http from "http"
import { autorun, reaction } from "mobx"; import { autorun, reaction } from "mobx";
import { apiKubePrefix } from "../common/vars"; import { apiKubePrefix } from "../common/vars";
import { ClusterId, clusterStore } from "../common/cluster-store" import { ClusterId, clusterStore } from "../common/cluster-store"
import { handleIpc } from "../common/ipc"; import { Cluster } from "./cluster"
import { Cluster, ClusterIpcChannel } from "./cluster" import { clusterIpc } from "../common/cluster-ipc";
import logger from "./logger"; import logger from "./logger";
import { tracker } from "../common/tracker";
export class ClusterManager { export class ClusterManager {
protected activeClusterId: ClusterId; 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) // listen for ipc-events that must/can be handled *only* in main-process (nodeIntegration=true)
handleIpc(ClusterIpcChannel.INIT, this.onClusterInit); clusterIpc.refresh.handleInMain();
handleIpc(ClusterIpcChannel.DISCONNECT, this.onClusterDisconnect); clusterIpc.disconnect.handleInMain();
handleIpc(ClusterIpcChannel.RECONNECT, this.onClusterReconnect); clusterIpc.reconnect.handleInMain();
} }
stop() { 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) { protected getCluster(id: ClusterId) {
return clusterStore.getById(id); return clusterStore.getById(id);
} }

View File

@ -13,12 +13,6 @@ import { getFeatures, installFeature, uninstallFeature, upgradeFeature } from ".
import request, { RequestPromiseOptions } from "request-promise-native" import request, { RequestPromiseOptions } from "request-promise-native"
import logger from "./logger" import logger from "./logger"
export enum ClusterIpcChannel {
INIT = "cluster:init",
DISCONNECT = "cluster:disconnect",
RECONNECT = "cluster:reconnect",
}
export enum ClusterStatus { export enum ClusterStatus {
AccessGranted = 2, AccessGranted = 2,
AccessDenied = 1, AccessDenied = 1,
@ -341,7 +335,7 @@ export class Cluster implements ClusterModel {
} }
pushState = (clusterState = this.getState()) => { pushState = (clusterState = this.getState()) => {
logger.info(`[CLUSTER]: push-state`, clusterState); logger.debug(`[CLUSTER]: push-state`, clusterState);
broadcastIpc({ broadcastIpc({
// webContentId: viewId, // todo: send to cluster-view only // webContentId: viewId, // todo: send to cluster-view only
channel: "cluster:state", channel: "cluster:state",
@ -354,6 +348,8 @@ export class Cluster implements ClusterModel {
return { return {
id: this.id, id: this.id,
name: this.contextName, name: this.contextName,
initialized: this.initialized,
accessible: this.accessible,
} }
} }
} }

View File

@ -1,7 +1,7 @@
import "./cluster.scss" import "./cluster.scss"
import React from "react"; import React from "react";
import { computed, reaction } from "mobx"; import { computed, reaction, when } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { MainLayout } from "../layout/main-layout"; import { MainLayout } from "../layout/main-layout";
import { ClusterIssues } from "./cluster-issues"; import { ClusterIssues } from "./cluster-issues";
@ -13,6 +13,7 @@ import { nodesStore } from "../+nodes/nodes.store";
import { podsStore } from "../+workloads-pods/pods.store"; import { podsStore } from "../+workloads-pods/pods.store";
import { clusterStore } from "./cluster.store"; import { clusterStore } from "./cluster.store";
import { eventStore } from "../+events/event.store"; import { eventStore } from "../+events/event.store";
import { configStore } from "../../config.store";
import { isAllowedResource } from "../../api/rbac"; import { isAllowedResource } from "../../api/rbac";
@observer @observer
@ -24,7 +25,10 @@ export class Cluster extends React.Component {
private dependentStores = [nodesStore, podsStore]; private dependentStores = [nodesStore, podsStore];
// todo: refactor
async componentDidMount() { async componentDidMount() {
await when(() => configStore.isLoaded);
const { dependentStores } = this; const { dependentStores } = this;
if (!isAllowedResource("nodes")) { if (!isAllowedResource("nodes")) {
dependentStores.splice(dependentStores.indexOf(nodesStore), 1) dependentStores.splice(dependentStores.indexOf(nodesStore), 1)

View File

@ -2,7 +2,6 @@ import "./app.scss";
import React from "react"; import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { i18nStore } from "../i18n"; import { i18nStore } from "../i18n";
import { configStore } from "../config.store";
import { Terminal } from "./dock/terminal"; import { Terminal } from "./dock/terminal";
import { Redirect, Route, Switch } from "react-router"; import { Redirect, Route, Switch } from "react-router";
import { Notifications } from "./notifications"; import { Notifications } from "./notifications";
@ -35,6 +34,7 @@ import { clusterStore } from "../../common/cluster-store";
import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings"; import { ClusterSettings, clusterSettingsRoute } from "./+cluster-settings";
import { Workspaces, workspacesRoute } from "./+workspaces"; import { Workspaces, workspacesRoute } from "./+workspaces";
import { ErrorBoundary } from "./error-boundary"; import { ErrorBoundary } from "./error-boundary";
import { configStore } from "../config.store";
@observer @observer
export class App extends React.Component { export class App extends React.Component {

View File

@ -1,15 +1,14 @@
import "./cluster-manager.scss" import "./cluster-manager.scss"
import React from "react"; import React from "react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { computed, observable } from "mobx"; import { observable } from "mobx";
import { App } from "../app"; import { App } from "../app";
import { ClusterStatus } from "./cluster-status"; import { ClusterStatus } from "./cluster-status";
import { ClustersMenu } from "./clusters-menu"; import { ClustersMenu } from "./clusters-menu";
import { BottomBar } from "./bottom-bar"; import { BottomBar } from "./bottom-bar";
import { cssNames, IClassName } from "../../utils"; import { cssNames, IClassName } from "../../utils";
import { invokeIpc } from "../../../common/ipc";
import { ClusterIpcChannel } from "../../../main/cluster";
import { clusterStore } from "../../../common/cluster-store"; import { clusterStore } from "../../../common/cluster-store";
import { clusterIpc } from "../../../common/cluster-ipc";
interface Props { interface Props {
className?: IClassName; className?: IClassName;
@ -18,21 +17,17 @@ interface Props {
@observer @observer
export class ClusterManager extends React.Component<Props> { export class ClusterManager extends React.Component<Props> {
@observable appReady = false; @observable isReady = false;
@computed get clusterReady() {
return clusterStore.activeCluster?.isReady
}
async componentDidMount() { async componentDidMount() {
invokeIpc(ClusterIpcChannel.INIT); clusterIpc.refresh.invokeFromRenderer();
await App.init(); await App.init();
this.appReady = true; this.isReady = true;
} }
render() { render() {
const { className, contentClass } = this.props; const { className, contentClass } = this.props;
const isReady = this.appReady && this.clusterReady; const isReady = this.isReady && clusterStore.activeCluster?.isReady;
return ( return (
<div className={cssNames("ClusterManager", className)}> <div className={cssNames("ClusterManager", className)}>
<div id="draggable-top"/> <div id="draggable-top"/>

View File

@ -1,8 +1,6 @@
import "./cluster-status.scss" import "./cluster-status.scss"
import React from "react"; import React from "react";
import type { KubeAuthProxyResponse } from "../../../main/kube-auth-proxy"; 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 { clusterStore } from "../../../common/cluster-store";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import { observable } from "mobx"; import { observable } from "mobx";
@ -10,6 +8,7 @@ import { observer } from "mobx-react";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { Button } from "../button"; import { Button } from "../button";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
import { clusterIpc } from "../../../common/cluster-ipc";
@observer @observer
export class ClusterStatus extends React.Component { export class ClusterStatus extends React.Component {
@ -36,7 +35,7 @@ export class ClusterStatus extends React.Component {
reconnect = () => { reconnect = () => {
this.authOutput = ["Reconnecting ...\n"]; this.authOutput = ["Reconnecting ...\n"];
invokeIpc(ClusterIpcChannel.RECONNECT, this.clusterId); clusterIpc.reconnect.invokeFromRenderer(this.clusterId);
} }
render() { render() {

View File

@ -3,7 +3,7 @@ import { observable, when } from "mobx";
import { autobind, interval } from "./utils"; import { autobind, interval } from "./utils";
import { apiBase } from "./api"; 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() @autobind()
export class ConfigStore { export class ConfigStore {

View File

@ -24,7 +24,7 @@ class LensApp extends React.Component {
userStore.load(), userStore.load(),
workspaceStore.load(), workspaceStore.load(),
clusterStore.load(), clusterStore.load(),
]); ])
render(<LensApp/>, rootElem); render(<LensApp/>, rootElem);
} }