mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make cluster state sync fully injectable
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
659b63d0cf
commit
f7b5ae7b57
@ -4,14 +4,12 @@
|
||||
*/
|
||||
|
||||
|
||||
import { ipcMain, ipcRenderer, webFrame } from "electron";
|
||||
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
|
||||
import { action, comparer, computed, makeObservable, observable } from "mobx";
|
||||
import type { BaseStoreDependencies } from "../base-store/base-store";
|
||||
import { BaseStore } from "../base-store/base-store";
|
||||
import { Cluster } from "../cluster/cluster";
|
||||
import { disposer, toJS } from "../utils";
|
||||
import type { ClusterModel, ClusterId, ClusterState } from "../cluster-types";
|
||||
import { requestInitialClusterStates } from "../../renderer/ipc";
|
||||
import { toJS } from "../utils";
|
||||
import type { ClusterModel, ClusterId } from "../cluster-types";
|
||||
import type { CreateCluster } from "../cluster/create-cluster-injection-token";
|
||||
import type { ReadClusterConfigSync } from "./read-cluster-config.injectable";
|
||||
import type { EmitAppEvent } from "../app-event-bus/emit-event.injectable";
|
||||
@ -29,8 +27,6 @@ interface Dependencies extends BaseStoreDependencies {
|
||||
export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
readonly clusters = observable.map<ClusterId, Cluster>();
|
||||
|
||||
protected readonly disposer = disposer();
|
||||
|
||||
constructor(protected readonly dependencies: Dependencies) {
|
||||
super(dependencies, {
|
||||
configName: "lens-cluster-store",
|
||||
@ -41,39 +37,6 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||
});
|
||||
|
||||
makeObservable(this);
|
||||
this.load();
|
||||
this.pushStateToViewsAutomatically();
|
||||
}
|
||||
|
||||
async loadInitialOnRenderer() {
|
||||
this.dependencies.logger.info("[CLUSTER-STORE] requesting initial state sync");
|
||||
|
||||
for (const { id, state } of await requestInitialClusterStates()) {
|
||||
this.getById(id)?.setState(state);
|
||||
}
|
||||
}
|
||||
|
||||
protected pushStateToViewsAutomatically() {
|
||||
if (ipcMain) {
|
||||
this.disposer.push(
|
||||
reaction(() => this.connectedClustersList, () => this.pushState()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
registerIpcListener() {
|
||||
this.dependencies.logger.info(`[CLUSTER-STORE] start to listen (${webFrame.routingId})`);
|
||||
const ipc = ipcMain ?? ipcRenderer;
|
||||
|
||||
ipc?.on("cluster:state", (event, clusterId: ClusterId, state: ClusterState) => {
|
||||
this.getById(clusterId)?.setState(state);
|
||||
});
|
||||
}
|
||||
|
||||
pushState() {
|
||||
this.clusters.forEach((c) => {
|
||||
c.pushState();
|
||||
});
|
||||
}
|
||||
|
||||
@computed get clustersList(): Cluster[] {
|
||||
|
||||
@ -316,7 +316,6 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
const refreshMetadataTimer = setInterval(() => this.available && this.refreshAccessibilityAndMetadata(), 900000); // every 15 minutes
|
||||
|
||||
this.eventsDisposer.push(
|
||||
reaction(() => this.getState(), state => this.pushState(state)),
|
||||
reaction(
|
||||
() => this.prometheusPreferences,
|
||||
prefs => this.contextHandler.setupPrometheus(prefs),
|
||||
@ -349,7 +348,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
@action
|
||||
async activate(force = false) {
|
||||
if (this.activated && !force) {
|
||||
return this.pushState();
|
||||
return;
|
||||
}
|
||||
|
||||
this.dependencies.logger.info(`[CLUSTER]: activate`, this.getMeta());
|
||||
@ -395,7 +394,6 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
}
|
||||
|
||||
this.activated = true;
|
||||
this.pushState();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -437,7 +435,6 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
this.activated = false;
|
||||
this.allowedNamespaces = [];
|
||||
this.resourceAccessStatuses.clear();
|
||||
this.pushState();
|
||||
this.dependencies.logger.info(`[CLUSTER]: disconnected`, { id: this.id });
|
||||
}
|
||||
|
||||
@ -448,7 +445,6 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
async refresh() {
|
||||
this.dependencies.logger.info(`[CLUSTER]: refresh`, this.getMeta());
|
||||
await this.refreshConnectionStatus();
|
||||
this.pushState();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -614,16 +610,15 @@ export class Cluster implements ClusterModel, ClusterState {
|
||||
* @param state cluster state
|
||||
*/
|
||||
@action setState(state: ClusterState) {
|
||||
Object.assign(this, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @param state cluster state
|
||||
*/
|
||||
pushState(state = this.getState()) {
|
||||
this.dependencies.logger.silly(`[CLUSTER]: push-state`, state);
|
||||
this.dependencies.broadcastMessage("cluster:state", this.id, state);
|
||||
this.accessible = state.accessible;
|
||||
this.allowedNamespaces = state.allowedNamespaces;
|
||||
this.allowedResources = state.allowedResources;
|
||||
this.apiUrl = state.apiUrl;
|
||||
this.disconnected = state.disconnected;
|
||||
this.isAdmin = state.isAdmin;
|
||||
this.isGlobalWatchEnabled = state.isGlobalWatchEnabled;
|
||||
this.online = state.online;
|
||||
this.ready = state.ready;
|
||||
}
|
||||
|
||||
// get cluster system meta, e.g. use in "logger"
|
||||
|
||||
21
src/features/cluster/state-sync/common/channels.ts
Normal file
21
src/features/cluster/state-sync/common/channels.ts
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { ClusterId, ClusterState } from "../../../../common/cluster-types";
|
||||
import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
|
||||
|
||||
export interface ClusterStateSync {
|
||||
clusterId: ClusterId;
|
||||
state: ClusterState;
|
||||
}
|
||||
|
||||
export const clusterStateSyncChannel: MessageChannel<ClusterStateSync> = {
|
||||
id: "cluster-state-sync",
|
||||
};
|
||||
|
||||
export const initialClusterStatesChannel: RequestChannel<void, ClusterStateSync[]> = {
|
||||
id: "initial-cluster-state-sync",
|
||||
};
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token";
|
||||
import { clusterStateSyncChannel } from "../common/channels";
|
||||
|
||||
export type EmitClusterStateUpdate = MessageChannelHandler<typeof clusterStateSyncChannel>;
|
||||
|
||||
const emitClusterStateUpdateInjectable = getInjectable({
|
||||
id: "emit-cluster-state-update",
|
||||
instantiate: (di): EmitClusterStateUpdate => {
|
||||
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
|
||||
|
||||
return (message) => sendMessageToChannel(clusterStateSyncChannel, message);
|
||||
},
|
||||
});
|
||||
|
||||
export default emitClusterStateUpdateInjectable;
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import { initialClusterStatesChannel } from "../common/channels";
|
||||
|
||||
const handleInitialClusterStateSyncInjectable = getRequestChannelListenerInjectable({
|
||||
channel: initialClusterStatesChannel,
|
||||
handler: (di) => {
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
|
||||
return () => clusterStore.clustersList.map(cluster => ({
|
||||
clusterId: cluster.id,
|
||||
state: cluster.getState(),
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
export default handleInitialClusterStateSyncInjectable;
|
||||
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { reaction } from "mobx";
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import { beforeApplicationIsLoadingInjectionToken } from "../../../../main/start-main-application/runnable-tokens/before-application-is-loading-injection-token";
|
||||
import initClusterStoreInjectable from "../../store/main/init.injectable";
|
||||
import emitClusterStateUpdateInjectable from "./emit-update.injectable";
|
||||
|
||||
const setupClusterStateBroadcastingInjectable = getInjectable({
|
||||
id: "setup-cluster-state-broadcasting",
|
||||
instantiate: (di) => {
|
||||
const emitClusterStateUpdate = di.inject(emitClusterStateUpdateInjectable);
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
|
||||
return {
|
||||
id: "setup-cluster-state-broadcasting",
|
||||
run: () => {
|
||||
reaction(() => clusterStore.connectedClustersList, () => {
|
||||
for (const cluster of clusterStore.clusters.values()) {
|
||||
emitClusterStateUpdate({
|
||||
clusterId: cluster.id,
|
||||
state: cluster.getState(),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
runAfter: di.inject(initClusterStoreInjectable),
|
||||
};
|
||||
},
|
||||
injectionToken: beforeApplicationIsLoadingInjectionToken,
|
||||
});
|
||||
|
||||
export default setupClusterStateBroadcastingInjectable;
|
||||
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
|
||||
import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
|
||||
import { clusterStateSyncChannel } from "../common/channels";
|
||||
|
||||
const clusterStateListenerInjectable = getMessageChannelListenerInjectable({
|
||||
channel: clusterStateSyncChannel,
|
||||
id: "main",
|
||||
handler: (di) => {
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
|
||||
return ({ clusterId, state }) => getClusterById(clusterId)?.setState(state);
|
||||
},
|
||||
});
|
||||
|
||||
export default clusterStateListenerInjectable;
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
|
||||
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
|
||||
import { initialClusterStatesChannel } from "../common/channels";
|
||||
|
||||
export type RequestInitialClusterStates = RequestChannelHandler<typeof initialClusterStatesChannel>;
|
||||
|
||||
const requestInitialClusterStatesInjectable = getInjectable({
|
||||
id: "request-initial-cluster-states",
|
||||
instantiate: (di): RequestInitialClusterStates => {
|
||||
const requestFromChannel = di.inject(requestFromChannelInjectable);
|
||||
|
||||
return () => requestFromChannel(initialClusterStatesChannel);
|
||||
},
|
||||
});
|
||||
|
||||
export default requestInitialClusterStatesInjectable;
|
||||
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import getClusterByIdInjectable from "../../../../common/cluster-store/get-by-id.injectable";
|
||||
import { beforeFrameStartsInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
|
||||
import initClusterStoreInjectable from "../../store/renderer/init.injectable";
|
||||
import requestInitialClusterStatesInjectable from "./request-initial.injectable";
|
||||
|
||||
const setupClusterStateSyncInjectable = getInjectable({
|
||||
id: "setup-cluster-state-sync",
|
||||
instantiate: (di) => {
|
||||
const requestInitialClusterStates = di.inject(requestInitialClusterStatesInjectable);
|
||||
const getClusterById = di.inject(getClusterByIdInjectable);
|
||||
|
||||
return {
|
||||
id: "setup-cluster-state-sync",
|
||||
run: async () => {
|
||||
const initalStates = await requestInitialClusterStates();
|
||||
|
||||
for (const { clusterId, state } of initalStates) {
|
||||
getClusterById(clusterId)?.setState(state);
|
||||
}
|
||||
},
|
||||
runAfter: di.inject(initClusterStoreInjectable),
|
||||
};
|
||||
},
|
||||
injectionToken: beforeFrameStartsInjectionToken,
|
||||
});
|
||||
|
||||
export default setupClusterStateSyncInjectable;
|
||||
26
src/features/cluster/store/main/init.injectable.ts
Normal file
26
src/features/cluster/store/main/init.injectable.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import { beforeApplicationIsLoadingInjectionToken } from "../../../../main/start-main-application/runnable-tokens/before-application-is-loading-injection-token";
|
||||
import initUserStoreInjectable from "../../../../main/stores/init-user-store.injectable";
|
||||
|
||||
const initClusterStoreInjectable = getInjectable({
|
||||
id: "init-cluster-store",
|
||||
instantiate: (di) => {
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
|
||||
return {
|
||||
id: "init-cluster-store",
|
||||
run: () => {
|
||||
clusterStore.load();
|
||||
},
|
||||
runAfter: di.inject(initUserStoreInjectable),
|
||||
};
|
||||
},
|
||||
injectionToken: beforeApplicationIsLoadingInjectionToken,
|
||||
});
|
||||
|
||||
export default initClusterStoreInjectable;
|
||||
26
src/features/cluster/store/renderer/init.injectable.ts
Normal file
26
src/features/cluster/store/renderer/init.injectable.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable";
|
||||
import { beforeFrameStartsInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
|
||||
import initUserStoreInjectable from "../../../../renderer/stores/init-user-store.injectable";
|
||||
|
||||
const initClusterStoreInjectable = getInjectable({
|
||||
id: "init-cluster-store",
|
||||
instantiate: (di) => {
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
|
||||
return {
|
||||
id: "init-cluster-store",
|
||||
run: () => {
|
||||
clusterStore.load();
|
||||
},
|
||||
runAfter: di.inject(initUserStoreInjectable),
|
||||
};
|
||||
},
|
||||
injectionToken: beforeFrameStartsInjectionToken,
|
||||
});
|
||||
|
||||
export default initClusterStoreInjectable;
|
||||
@ -20,7 +20,6 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import extensionLoaderInjectable from "../extensions/extension-loader/extension-loader.injectable";
|
||||
import extensionDiscoveryInjectable from "../extensions/extension-discovery/extension-discovery.injectable";
|
||||
import extensionInstallationStateStoreInjectable from "../extensions/extension-installation-state-store/extension-installation-state-store.injectable";
|
||||
import clusterStoreInjectable from "../common/cluster-store/cluster-store.injectable";
|
||||
import initRootFrameInjectable from "./frames/root-frame/init-root-frame/init-root-frame.injectable";
|
||||
import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable";
|
||||
import { Router } from "react-router";
|
||||
@ -47,11 +46,6 @@ export async function bootstrap(di: DiContainer) {
|
||||
|
||||
extensionDiscovery.init();
|
||||
|
||||
// ClusterStore depends on: UserStore
|
||||
const clusterStore = di.inject(clusterStoreInjectable);
|
||||
|
||||
await clusterStore.loadInitialOnRenderer();
|
||||
|
||||
// HotbarStore depends on: ClusterStore
|
||||
di.inject(hotbarStoreInjectable).load();
|
||||
|
||||
@ -63,9 +57,6 @@ export async function bootstrap(di: DiContainer) {
|
||||
|
||||
extensionInstallationStateStore.bindIpcListeners();
|
||||
|
||||
// Register additional store listeners
|
||||
clusterStore.registerIpcListener();
|
||||
|
||||
let App;
|
||||
let initializeApp;
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import userStoreInjectable from "../../common/user-store/user-store.injectable";
|
||||
import setupAppPathsInjectable from "../app-paths/setup-app-paths.injectable";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/before-frame-starts-injection-token";
|
||||
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/tokens";
|
||||
import initDefaultUpdateChannelInjectable from "../vars/default-update-channel/init.injectable";
|
||||
|
||||
const initUserStoreInjectable = getInjectable({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user