Fix rerendering of KubeObject views every 30s (#4801)

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>
Co-authored-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
authored and GitHub committed 2022-02-03 09:11:28 -05:00
1 parent 00314aabc0
commit 76f48df56b
105 files changed
+1442 -709

No files matched your search

@@ -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, lifecycleEnum } from "@ogre-tools/injectable";
import { comparer, computed } from "mobx";
import hostedClusterInjectable from "./hosted-cluster.injectable";
const allowedResourcesInjectable = getInjectable({
instantiate: (di) => {
const cluster = di.inject(hostedClusterInjectable);
return computed(() => new Set(cluster.allowedResources), {
// This needs to be here so that during refresh changes are only propogated when necessary
equals: (cur, prev) => comparer.structural(cur, prev),
});
},
lifecycle: lifecycleEnum.singleton,
});
export default allowedResourcesInjectable;
@@ -3,8 +3,8 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { getHostedClusterId } from "../../utils";
import clusterStoreInjectable from "../cluster-store.injectable";
import { getHostedClusterId } from "../utils";
import clusterStoreInjectable from "./cluster-store.injectable";
const hostedClusterInjectable = getInjectable({
instantiate: (di) => {
@@ -7,7 +7,7 @@ import yaml from "js-yaml";
import { formatDuration } from "../../utils";
import capitalize from "lodash/capitalize";
import { apiBase } from "../index";
import { helmChartStore } from "../../../renderer/components/+apps-helm-charts/helm-chart.store";
import { helmChartStore } from "../../../renderer/components/+helm-charts/helm-chart.store";
import type { ItemObject } from "../../item.store";
import { KubeObject } from "../kube-object";
import type { JsonApiData } from "../json-api";
+3 -14
View File
@@ -16,12 +16,9 @@ import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object";
import byline from "byline";
import type { IKubeWatchEvent } from "./kube-watch-event";
import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api";
import { noop } from "../utils";
import { noop, WrappedAbortController } from "../utils";
import type { RequestInit } from "node-fetch";
// BUG: https://github.com/mysticatea/abort-controller/pull/22
// eslint-disable-next-line import/no-named-as-default
import AbortController from "abort-controller";
import type AbortController from "abort-controller";
import { Agent, AgentOptions } from "https";
import type { Patch } from "rfc6902";
@@ -582,14 +579,7 @@ export class KubeApi<T extends KubeObject> {
const { watchId = `${this.kind.toLowerCase()}-${this.watchId++}` } = opts;
// Create AbortController for this request
const abortController = new AbortController();
// If caller aborts, abort using request's abortController
if (opts.abortController) {
opts.abortController.signal.addEventListener("abort", () => {
abortController.abort();
});
}
const abortController = new WrappedAbortController(opts.abortController);
abortController.signal.addEventListener("abort", () => {
logger.info(`[KUBE-API] watch (${watchId}) aborted ${watchUrl}`);
@@ -687,7 +677,6 @@ export class KubeApi<T extends KubeObject> {
protected modifyWatchEvent(event: IKubeWatchEvent<KubeJsonApiData>) {
if (event.type === "ERROR") {
return;
}
ensureObjectSelfLink(this, event.object);
+2 -2
View File
@@ -6,7 +6,7 @@
import type { ClusterContext } from "./cluster-context";
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
import { autoBind, noop, rejectPromiseBy } from "../utils";
import { autoBind, Disposer, noop, rejectPromiseBy } from "../utils";
import { KubeObject, KubeStatus } from "./kube-object";
import type { IKubeWatchEvent } from "./kube-watch-event";
import { ItemStore } from "../item.store";
@@ -378,7 +378,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
});
}
subscribe({ onLoadFailure, abortController = new AbortController() }: KubeObjectStoreSubscribeParams = {}) {
subscribe({ onLoadFailure, abortController = new AbortController() }: KubeObjectStoreSubscribeParams = {}): Disposer {
if (this.api.isNamespaced) {
Promise.race([rejectPromiseBy(abortController.signal), Promise.all([this.contextReady, this.namespacesReady])])
.then(() => {
+2 -2
View File
@@ -5,10 +5,10 @@
import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl";
import { appsRoute } from "./apps";
import { helmRoute } from "./helm";
export const helmChartsRoute: RouteProps = {
path: `${appsRoute.path}/charts/:repo?/:chartName?`,
path: `${helmRoute.path}/charts/:repo?/:chartName?`,
};
export interface HelmChartsRouteParams {
@@ -6,8 +6,8 @@
import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl";
export const appsRoute: RouteProps = {
path: "/apps",
export const helmRoute: RouteProps = {
path: "/helm",
};
export const appsURL = buildURL(appsRoute.path);
export const helmURL = buildURL(helmRoute.path);
+1 -1
View File
@@ -4,7 +4,6 @@
*/
export * from "./add-cluster";
export * from "./apps";
export * from "./catalog";
export * from "./cluster-view";
export * from "./cluster";
@@ -16,6 +15,7 @@ export * from "./entity-settings";
export * from "./events";
export * from "./extensions";
export * from "./helm-charts";
export * from "./helm";
export * from "./hpa";
export * from "./ingresses";
export * from "./limit-ranges";
+2 -2
View File
@@ -5,10 +5,10 @@
import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl";
import { appsRoute } from "./apps";
import { helmRoute } from "./helm";
export const releaseRoute: RouteProps = {
path: `${appsRoute.path}/releases/:namespace?/:name?`,
path: `${helmRoute.path}/releases/:namespace?/:name?`,
};
export interface ReleaseRouteParams {
+15
View File
@@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import AbortController from "abort-controller";
export class WrappedAbortController extends AbortController {
constructor(parent?: AbortController) {
super();
parent?.signal.addEventListener("abort", () => {
this.abort();
});
}
}
-25
View File
@@ -1,25 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { ClusterStore } from "../cluster-store/cluster-store";
import type { KubeResource } from "../rbac";
import { getHostedClusterId } from "./cluster-id-url-parsing";
export function isAllowedResource(resource: KubeResource | KubeResource[]) {
const resources = [resource].flat();
const cluster = ClusterStore.getInstance().getById(getHostedClusterId());
if (!cluster?.allowedResources) {
return false;
}
if (resources.length === 0) {
return true;
}
const allowedResources = new Set(cluster.allowedResources);
return resources.every(resource => allowedResources.has(resource));
}
+1
View File
@@ -10,6 +10,7 @@ export function noop<T extends any[]>(...args: T): void {
return void args;
}
export * from "./abort-controller";
export * from "./app-version";
export * from "./autobind";
export * from "./camelCase";
@@ -0,0 +1,22 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import allowedResourcesInjectable from "../cluster-store/allowed-resources.injectable";
import type { KubeResource } from "../rbac";
export type IsAllowedResource = (resource: KubeResource) => boolean;
// TODO: This injectable obscures MobX de-referencing. Make it more apparent in usage.
const isAllowedResourceInjectable = getInjectable({
instantiate: (di) => {
const allowedResources = di.inject(allowedResourcesInjectable);
return (resource: KubeResource) => allowedResources.get().has(resource);
},
lifecycle: lifecycleEnum.singleton,
});
export default isAllowedResourceInjectable;