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

store subscribing refactoring -- part 2

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-01-22 13:52:18 +02:00
parent 3e005fc611
commit 1f4599ee50
7 changed files with 54 additions and 45 deletions

View File

@ -22,8 +22,8 @@ export interface IKubeWatchMessage<T extends KubeObject = any> {
} }
export interface IKubeWatchSubscribeStoreOptions { export interface IKubeWatchSubscribeStoreOptions {
autoLoad?: boolean; preload?: boolean; // preload store items, default: true
waitUntilLoaded?: boolean; waitUntilLoaded?: boolean; // subscribe only after loading all stores, default: true
} }
export interface IKubeWatchLog { export interface IKubeWatchLog {
@ -79,32 +79,41 @@ export class KubeWatchApi {
}; };
} }
async subscribeStores(stores: KubeObjectStore[], options: IKubeWatchSubscribeStoreOptions = {}): Promise<() => void> { subscribeStores(stores: KubeObjectStore[], options: IKubeWatchSubscribeStoreOptions = {}): () => void {
this.log({ const { preload = true, waitUntilLoaded = true } = options;
message: "Subscribing to stores",
meta: { stores, options },
});
const { autoLoad = true, waitUntilLoaded = true } = options;
const loading: Promise<any>[] = []; const loading: Promise<any>[] = [];
const disposers: Function[] = [];
let isDisposed = false;
if (autoLoad) { async function subscribe() {
if (isDisposed) return;
const unsubscribeList = await Promise.all(stores.map(store => store.subscribe()));
disposers.push(...unsubscribeList);
if (isDisposed) unsubscribe();
}
function unsubscribe() {
isDisposed = true;
disposers.forEach(dispose => dispose());
disposers.length = 0;
}
if (preload) {
loading.push(...stores.map(store => store.loadAll())); loading.push(...stores.map(store => store.loadAll()));
} }
if (waitUntilLoaded) { if (waitUntilLoaded) {
try { Promise.all(loading).then(subscribe, error => {
await Promise.all(loading);
} catch (error) {
this.log({ this.log({
message: new Error("Loading stores has failed"), message: new Error("Loading stores has failed"),
meta: { stores, error, options }, meta: { stores, error, options },
}) });
} });
} else {
subscribe();
} }
const disposers = await Promise.all(stores.map(store => store.subscribe())); return unsubscribe;
return () => disposers.forEach(dispose => dispose()); // unsubscribe
} }
protected async resolveCluster(): Promise<Cluster> { protected async resolveCluster(): Promise<Cluster> {

View File

@ -24,12 +24,12 @@ export class ClusterOverview extends React.Component {
getHostedCluster().available && clusterOverviewStore.loadMetrics(); getHostedCluster().available && clusterOverviewStore.loadMetrics();
} }
async componentDidMount() { componentDidMount() {
this.metricPoller.start(true); this.metricPoller.start(true);
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await kubeWatchApi.subscribeStores([nodesStore, podsStore, eventStore], { kubeWatchApi.subscribeStores([nodesStore, podsStore, eventStore], {
autoLoad: true, preload: true,
}), }),
reaction( reaction(
() => clusterOverviewStore.metricNodeRole, // Toggle Master/Worker node switcher () => clusterOverviewStore.metricNodeRole, // Toggle Master/Worker node switcher

View File

@ -9,6 +9,7 @@ import { Icon } from "../icon";
import { namespaceStore } from "./namespace.store"; import { namespaceStore } from "./namespace.store";
import { FilterIcon } from "../item-object-list/filter-icon"; import { FilterIcon } from "../item-object-list/filter-icon";
import { FilterType } from "../item-object-list/page-filters.store"; import { FilterType } from "../item-object-list/page-filters.store";
import { kubeWatchApi } from "../../api/kube-watch-api";
interface Props extends SelectProps { interface Props extends SelectProps {
showIcons?: boolean; showIcons?: boolean;
@ -29,12 +30,11 @@ const defaultProps: Partial<Props> = {
export class NamespaceSelect extends React.Component<Props> { export class NamespaceSelect extends React.Component<Props> {
static defaultProps = defaultProps as object; static defaultProps = defaultProps as object;
async componentDidMount() { componentDidMount() {
if (!namespaceStore.isLoaded) {
await namespaceStore.loadAll();
}
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await namespaceStore.subscribe(), kubeWatchApi.subscribeStores([namespaceStore], {
preload: !namespaceStore.isLoaded,
})
]); ]);
} }

View File

@ -12,18 +12,18 @@ import { ServicePortComponent } from "./service-port-component";
import { endpointStore } from "../+network-endpoints/endpoints.store"; import { endpointStore } from "../+network-endpoints/endpoints.store";
import { ServiceDetailsEndpoint } from "./service-details-endpoint"; import { ServiceDetailsEndpoint } from "./service-details-endpoint";
import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry"; import { kubeObjectDetailRegistry } from "../../api/kube-object-detail-registry";
import { kubeWatchApi } from "../../api/kube-watch-api";
interface Props extends KubeObjectDetailsProps<Service> { interface Props extends KubeObjectDetailsProps<Service> {
} }
@observer @observer
export class ServiceDetails extends React.Component<Props> { export class ServiceDetails extends React.Component<Props> {
async componentDidMount() { componentDidMount() {
if (!endpointStore.isLoaded) {
endpointStore.loadAll();
}
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await endpointStore.subscribe(), kubeWatchApi.subscribeStores([endpointStore], {
preload: !endpointStore.isLoaded,
}),
]); ]);
} }

View File

@ -26,13 +26,14 @@ export class WorkloadsOverview extends React.Component<Props> {
@observable isLoading = false; @observable isLoading = false;
@observable isUnmounting = false; @observable isUnmounting = false;
async componentDidMount() { componentDidMount() {
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await kubeWatchApi.subscribeStores([ kubeWatchApi.subscribeStores([
podsStore, deploymentStore, daemonSetStore, podsStore, deploymentStore, daemonSetStore, statefulSetStore, replicaSetStore,
statefulSetStore, replicaSetStore,
jobStore, cronJobStore, eventStore, jobStore, cronJobStore, eventStore,
]) ], {
preload: true,
}),
]); ]);
// fixme: reload stores // fixme: reload stores

View File

@ -76,17 +76,14 @@ export class App extends React.Component {
whatInput.ask(); // Start to monitor user input device whatInput.ask(); // Start to monitor user input device
} }
async componentDidMount() { componentDidMount() {
const cluster = getHostedCluster();
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await kubeWatchApi.subscribeStores([podsStore, nodesStore, eventStore], { kubeWatchApi.subscribeStores([podsStore, nodesStore, eventStore], {
autoLoad: true, preload: true,
waitUntilLoaded: true,
}), }),
reaction(() => this.warningsCount, (count) => { reaction(() => this.warningsCount, (count) => {
broadcastMessage(`cluster-warning-event-count:${cluster.id}`, count); broadcastMessage(`cluster-warning-event-count:${getHostedCluster().id}`, count);
}), }),
]); ]);
} }

View File

@ -20,12 +20,14 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
return this.props.store.getByPath(kubeSelectedUrlParam.get()); return this.props.store.getByPath(kubeSelectedUrlParam.get());
} }
async componentDidMount() { componentDidMount() {
const { store, dependentStores } = this.props; const { store, dependentStores = [] } = this.props;
const stores = Array.from(new Set([store, ...dependentStores])); const stores = Array.from(new Set([store, ...dependentStores]));
disposeOnUnmount(this, [ disposeOnUnmount(this, [
await kubeWatchApi.subscribeStores(stores) kubeWatchApi.subscribeStores(stores, {
preload: true
})
]); ]);
} }