Fix infinite render loop in release details (#4710)

* Fix infinite render loop in release details by replacing stateful, UI-triggered releaseStore with reactive async computed

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Update injectable

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Remove unnecessary return

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Remove empty lines

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Allow injection of history

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Make data required for opening of release details a dependency to make sure it's present

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Remove dead code

Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com>

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Make arriving release values not re-render whole details

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne SavolainenandMikko Aspiala authored and GitHub committed 2022-01-21 16:29:10 +02:00
1 parent b7d29f8c49
commit 4f5a2988cb
33 files changed
+836 -600

No files matched your search

@@ -27,10 +27,10 @@ import type {
IReleaseCreatePayload,
IReleaseUpdateDetails,
} from "../../../common/k8s-api/endpoints/helm-releases.api";
import releaseStoreInjectable from "../+apps-releases/release-store.injectable";
import { withInjectables } from "@ogre-tools/injectable-react";
import installChartStoreInjectable from "./install-chart-store/install-chart-store.injectable";
import dockStoreInjectable from "./dock-store/dock-store.injectable";
import createReleaseInjectable from "../+apps-releases/create-release/create-release.injectable";
interface Props {
tab: DockTab;
@@ -222,7 +222,7 @@ export const InstallChart = withInjectables<Dependencies, Props>(
{
getProps: (di, props) => ({
createRelease: di.inject(releaseStoreInjectable).create,
createRelease: di.inject(createReleaseInjectable),
installChartStore: di.inject(installChartStoreInjectable),
dockStore: di.inject(dockStoreInjectable),
...props,
@@ -4,10 +4,10 @@
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { UpgradeChartStore } from "./upgrade-chart.store";
import releaseStoreInjectable from "../../+apps-releases/release-store.injectable";
import dockStoreInjectable from "../dock-store/dock-store.injectable";
import createDockTabStoreInjectable from "../dock-tab-store/create-dock-tab-store.injectable";
import createStorageInjectable from "../../../utils/create-storage/create-storage.injectable";
import releasesInjectable from "../../+apps-releases/releases.injectable";
const upgradeChartStoreInjectable = getInjectable({
instantiate: (di) => {
@@ -16,7 +16,7 @@ const upgradeChartStoreInjectable = getInjectable({
const valuesStore = createDockTabStore<string>();
return new UpgradeChartStore({
releaseStore: di.inject(releaseStoreInjectable),
releases: di.inject(releasesInjectable),
dockStore: di.inject(dockStoreInjectable),
createStorage: di.inject(createStorageInjectable),
valuesStore,
@@ -3,12 +3,22 @@
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { action, autorun, computed, IReactionDisposer, reaction, makeObservable } from "mobx";
import {
action,
autorun,
computed,
IReactionDisposer,
reaction,
makeObservable,
} from "mobx";
import { DockStore, DockTab, TabId, TabKind } from "../dock-store/dock.store";
import { DockTabStorageState, DockTabStore } from "../dock-tab-store/dock-tab.store";
import { getReleaseValues } from "../../../../common/k8s-api/endpoints/helm-releases.api";
import type { ReleaseStore } from "../../+apps-releases/release.store";
import {
getReleaseValues,
HelmRelease,
} from "../../../../common/k8s-api/endpoints/helm-releases.api";
import { iter, StorageHelper } from "../../../utils";
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
export interface IChartUpgradeData {
releaseName: string;
@@ -16,7 +26,7 @@ export interface IChartUpgradeData {
}
interface Dependencies {
releaseStore: ReleaseStore
releases: IAsyncComputed<HelmRelease[]>
valuesStore: DockTabStore<string>
dockStore: DockStore
createStorage: <T>(storageKey: string, options: DockTabStorageState<T>) => StorageHelper<DockTabStorageState<T>>
@@ -60,14 +70,14 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
return;
}
const dispose = reaction(() => {
const release = this.dependencies.releaseStore.getByName(releaseName);
const release = this.dependencies.releases.value.get().find(release => release.getName() === releaseName);
return release?.getRevision(); // watch changes only by revision
},
release => {
const releaseTab = this.getTabByRelease(releaseName);
if (!this.dependencies.releaseStore.isLoaded || !releaseTab) {
if (!releaseTab) {
return;
}
@@ -91,7 +101,7 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
isLoading(tabId = this.dependencies.dockStore.selectedTabId) {
const values = this.values.getData(tabId);
return !this.dependencies.releaseStore.isLoaded || values === undefined;
return values === undefined;
}
@action
@@ -99,7 +109,6 @@ export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
const values = this.values.getData(tabId);
await Promise.all([
!this.dependencies.releaseStore.isLoaded && this.dependencies.releaseStore.loadFromContextNamespaces(),
!values && this.loadValues(tabId),
]);
}
+18 -9
View File
@@ -13,15 +13,22 @@ import type { DockTab } from "./dock-store/dock.store";
import { InfoPanel } from "./info-panel";
import type { UpgradeChartStore } from "./upgrade-chart-store/upgrade-chart.store";
import { Spinner } from "../spinner";
import type { ReleaseStore } from "../+apps-releases/release.store";
import { Badge } from "../badge";
import { EditorPanel } from "./editor-panel";
import { helmChartStore, IChartVersion } from "../+apps-helm-charts/helm-chart.store";
import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
import {
helmChartStore,
IChartVersion,
} from "../+apps-helm-charts/helm-chart.store";
import type {
HelmRelease,
IReleaseUpdateDetails,
IReleaseUpdatePayload,
} from "../../../common/k8s-api/endpoints/helm-releases.api";
import { Select, SelectOption } from "../select";
import { withInjectables } from "@ogre-tools/injectable-react";
import releaseStoreInjectable from "../+apps-releases/release-store.injectable";
import { IAsyncComputed, withInjectables } from "@ogre-tools/injectable-react";
import upgradeChartStoreInjectable from "./upgrade-chart-store/upgrade-chart-store.injectable";
import updateReleaseInjectable from "../+apps-releases/update-release/update-release.injectable";
import releasesInjectable from "../+apps-releases/releases.injectable";
interface Props {
className?: string;
@@ -29,8 +36,9 @@ interface Props {
}
interface Dependencies {
releaseStore: ReleaseStore
releases: IAsyncComputed<HelmRelease[]>
upgradeChartStore: UpgradeChartStore
updateRelease: (name: string, namespace: string, payload: IReleaseUpdatePayload) => Promise<IReleaseUpdateDetails>
}
@observer
@@ -61,7 +69,7 @@ export class NonInjectedUpgradeChart extends React.Component<Props & Dependencie
if (!tabData) return null;
return this.props.releaseStore.getByName(tabData.releaseName);
return this.props.releases.value.get().find(release => release.getName() === tabData.releaseName);
}
get value() {
@@ -95,7 +103,7 @@ export class NonInjectedUpgradeChart extends React.Component<Props & Dependencie
const releaseName = this.release.getName();
const releaseNs = this.release.getNs();
await this.props.releaseStore.update(releaseName, releaseNs, {
await this.props.updateRelease(releaseName, releaseNs, {
chart: this.release.getChart(),
values: this.value,
repo, version,
@@ -167,7 +175,8 @@ export const UpgradeChart = withInjectables<Dependencies, Props>(
{
getProps: (di, props) => ({
releaseStore: di.inject(releaseStoreInjectable),
releases: di.inject(releasesInjectable),
updateRelease: di.inject(updateReleaseInjectable),
upgradeChartStore: di.inject(upgradeChartStoreInjectable),
...props,
}),