mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
refactoring & fixes
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
36d54c64fc
commit
4240d3afbc
@ -8,7 +8,7 @@ import type { ClusterContext } from "../components/context";
|
||||
|
||||
import plimit from "p-limit";
|
||||
import debounce from "lodash/debounce";
|
||||
import { comparer, computed, IReactionDisposer, observable, reaction, when } from "mobx";
|
||||
import { comparer, computed, IReactionDisposer, observable, reaction, toJS, when } from "mobx";
|
||||
import { autobind, EventEmitter, noop } from "../utils";
|
||||
import { ensureObjectSelfLink, KubeApi, parseKubeApi } from "./kube-api";
|
||||
import { KubeJsonApiData, KubeJsonApiError } from "./kube-json-api";
|
||||
@ -26,7 +26,7 @@ export interface IKubeWatchMessage<T extends KubeObject = any> {
|
||||
}
|
||||
|
||||
export interface IKubeWatchSubscribeStoreOptions {
|
||||
namespaces?: string[]; // todo: support custom namespaces to subscribe
|
||||
namespaces?: string[]; // default: all accessible namespaces
|
||||
preload?: boolean; // preload store items, default: true
|
||||
waitUntilLoaded?: boolean; // subscribe only after loading all stores, default: true
|
||||
loadOnce?: boolean; // check store.isLoaded to skip loading if done already, default: false
|
||||
@ -134,9 +134,7 @@ export class KubeWatchApi {
|
||||
preloading.push(limitRequests(async () => {
|
||||
if (store.isLoaded && opts.loadOnce) return; // skip
|
||||
|
||||
return store.loadAll({
|
||||
namespaces: opts.namespaces ?? this.context?.contextNamespaces,
|
||||
});
|
||||
return store.loadAll({ namespaces: opts.namespaces });
|
||||
}));
|
||||
}
|
||||
|
||||
@ -146,13 +144,14 @@ export class KubeWatchApi {
|
||||
};
|
||||
}
|
||||
|
||||
subscribeStores(stores: KubeObjectStore[], options: IKubeWatchSubscribeStoreOptions = {}): () => void {
|
||||
const { preload = true, waitUntilLoaded = true, loadOnce = false } = options;
|
||||
subscribeStores(stores: KubeObjectStore[], opts: IKubeWatchSubscribeStoreOptions = {}): () => void {
|
||||
const { preload = true, waitUntilLoaded = true, loadOnce = false, } = opts;
|
||||
const apis = new Set(stores.map(store => store.getSubscribeApis()).flat());
|
||||
const unsubscribeList: (() => void)[] = [];
|
||||
const unsubscribeList: Function[] = [];
|
||||
let isUnsubscribed = false;
|
||||
|
||||
const load = (namespaces?: string[]) => this.preloadStores(stores, { namespaces, loadOnce });
|
||||
const namespaces = opts.namespaces ?? this.context?.allNamespaces ?? [];
|
||||
const load = () => this.preloadStores(stores, { namespaces, loadOnce });
|
||||
let preloading = preload && load();
|
||||
let cancelReloading: IReactionDisposer = noop;
|
||||
|
||||
@ -166,17 +165,17 @@ export class KubeWatchApi {
|
||||
preloading.loading.then(subscribe, error => {
|
||||
this.log({
|
||||
message: new Error("Loading stores has failed"),
|
||||
meta: { stores, error, options },
|
||||
meta: { stores, error, options: opts },
|
||||
});
|
||||
});
|
||||
} else {
|
||||
subscribe();
|
||||
}
|
||||
|
||||
// partial reload only selected namespaces
|
||||
cancelReloading = reaction(() => this.context.contextNamespaces, namespaces => {
|
||||
// reload stores for requested namespaces
|
||||
cancelReloading = reaction(() => toJS(namespaces), () => {
|
||||
preloading?.cancelLoading();
|
||||
preloading = load(namespaces);
|
||||
preloading = load();
|
||||
}, {
|
||||
equals: comparer.shallow,
|
||||
});
|
||||
|
||||
@ -16,6 +16,7 @@ import { cronJobStore } from "../+workloads-cronjobs/cronjob.store";
|
||||
import { Events } from "../+events";
|
||||
import { isAllowedResource } from "../../../common/rbac";
|
||||
import { kubeWatchApi } from "../../api/kube-watch-api";
|
||||
import { clusterContext } from "../context";
|
||||
|
||||
interface Props extends RouteComponentProps<IWorkloadsOverviewRouteParams> {
|
||||
}
|
||||
@ -29,6 +30,7 @@ export class WorkloadsOverview extends React.Component<Props> {
|
||||
jobStore, cronJobStore, eventStore,
|
||||
], {
|
||||
preload: true,
|
||||
namespaces: clusterContext.contextNamespaces,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ interface IHeaderPlaceholders {
|
||||
export interface ItemListLayoutProps<T extends ItemObject = ItemObject> {
|
||||
tableId?: string;
|
||||
className: IClassName;
|
||||
items?: T[];
|
||||
store: ItemStore<T>;
|
||||
dependentStores?: ItemStore[];
|
||||
preloadStores?: boolean;
|
||||
@ -218,7 +219,8 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
}
|
||||
});
|
||||
|
||||
return this.applyFilters(filterItems, allItems);
|
||||
const items = this.props.items ?? allItems;
|
||||
return this.applyFilters(filterItems, items);
|
||||
}
|
||||
|
||||
@autobind()
|
||||
|
||||
@ -8,6 +8,7 @@ import { KubeObjectStore } from "../../kube-object.store";
|
||||
import { KubeObjectMenu } from "./kube-object-menu";
|
||||
import { kubeSelectedUrlParam, showDetails } from "./kube-object-details";
|
||||
import { kubeWatchApi } from "../../api/kube-watch-api";
|
||||
import { clusterContext } from "../context";
|
||||
|
||||
export interface KubeObjectListLayoutProps extends ItemListLayoutProps {
|
||||
store: KubeObjectStore;
|
||||
@ -26,7 +27,8 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
kubeWatchApi.subscribeStores(stores, {
|
||||
preload: true
|
||||
preload: true,
|
||||
namespaces: clusterContext.contextNamespaces,
|
||||
})
|
||||
]);
|
||||
}
|
||||
@ -40,12 +42,14 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
|
||||
};
|
||||
|
||||
render() {
|
||||
const items = this.props.store.contextItems;
|
||||
const { className, ...layoutProps } = this.props;
|
||||
|
||||
return (
|
||||
<ItemListLayout
|
||||
{...layoutProps}
|
||||
className={cssNames("KubeObjectListLayout", className)}
|
||||
items={items}
|
||||
preloadStores={false} // loading handled in kubeWatchApi.subscribeStores()
|
||||
detailsItem={this.selectedItem}
|
||||
onDetails={this.onDetails}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { ClusterContext } from "./components/context";
|
||||
|
||||
import { action, observable, reaction, when } from "mobx";
|
||||
import { action, computed, observable, reaction, when } from "mobx";
|
||||
import { autobind } from "./utils";
|
||||
import { KubeObject } from "./api/kube-object";
|
||||
import { IKubeWatchEvent, IKubeWatchMessage, kubeWatchApi } from "./api/kube-watch-api";
|
||||
@ -24,13 +24,22 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
|
||||
contextReady = when(() => Boolean(this.context));
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.bindWatchEventsUpdater();
|
||||
}
|
||||
|
||||
get context(): ClusterContext {
|
||||
return KubeObjectStore.defaultContext;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.bindWatchEventsUpdater();
|
||||
@computed get contextItems(): T[] {
|
||||
const namespaces = this.context?.contextNamespaces ?? [];
|
||||
|
||||
return this.items.filter(item => {
|
||||
const itemNamespace = item.getNs();
|
||||
return !itemNamespace /* cluster-wide */ || namespaces.includes(itemNamespace);
|
||||
});
|
||||
}
|
||||
|
||||
get query(): IKubeApiQueryParams {
|
||||
@ -107,21 +116,22 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
}
|
||||
|
||||
@action
|
||||
async loadAll({ namespaces = [], merge = true } = {}): Promise<void | T[]> {
|
||||
async loadAll(options: { namespaces?: string[], merge?: boolean } = {}): Promise<void | T[]> {
|
||||
await this.contextReady;
|
||||
this.isLoading = true;
|
||||
|
||||
try {
|
||||
if (!namespaces.length) {
|
||||
namespaces = this.context.allNamespaces; // load all available namespaces by default
|
||||
}
|
||||
const {
|
||||
namespaces = this.context.allNamespaces, // load all namespaces by default
|
||||
merge = true, // merge loaded items or return as result
|
||||
} = options;
|
||||
|
||||
const items = await this.loadItems({ namespaces, api: this.api });
|
||||
|
||||
this.isLoaded = true;
|
||||
|
||||
if (merge) {
|
||||
this.mergeItems(items);
|
||||
this.mergeItems(items, { replace: false });
|
||||
} else {
|
||||
return items;
|
||||
}
|
||||
@ -134,7 +144,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
}
|
||||
|
||||
@action
|
||||
reloadAll(opts: { namespaces?: string[], merge?: boolean, force?: boolean } = {}) {
|
||||
reloadAll(opts: { force?: boolean, namespaces?: string[], merge?: boolean } = {}) {
|
||||
const { force = false, ...loadingOptions } = opts;
|
||||
|
||||
if (this.isLoading || (this.isLoaded && !force)) {
|
||||
@ -145,7 +155,7 @@ export abstract class KubeObjectStore<T extends KubeObject = any> extends ItemSt
|
||||
}
|
||||
|
||||
@action
|
||||
mergeItems(partialItems: T[], { replace = true, updateStore = true, sort = true, filter = true } = {}): T[] {
|
||||
mergeItems(partialItems: T[], { replace = false, updateStore = true, sort = true, filter = true } = {}): T[] {
|
||||
let items = partialItems;
|
||||
|
||||
// update existing items
|
||||
|
||||
Loading…
Reference in New Issue
Block a user