Skip to content

Commit

Permalink
Merge pull request #2627 from headlamp-k8s/link-preload
Browse files Browse the repository at this point in the history
frontend: Populate query cache when kubeObject is passed into a Link
  • Loading branch information
joaquimrocha authored Dec 10, 2024
2 parents 9928715 + 3b423a4 commit 1c0e695
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 10 deletions.
39 changes: 34 additions & 5 deletions frontend/src/components/common/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import MuiLink from '@mui/material/Link';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { kubeObjectQueryKey, useEndpoints } from '../../lib/k8s/api/v2/hooks';
import { KubeObject } from '../../lib/k8s/KubeObject';
import { createRouteURL, RouteURLProps } from '../../lib/router';
import { LightTooltip } from './Tooltip';
Expand Down Expand Up @@ -28,14 +30,41 @@ export interface LinkObjectProps extends LinkBaseProps {
[prop: string]: any;
}

function KubeObjectLink(props: { kubeObject: KubeObject; [prop: string]: any }) {
const { kubeObject, ...otherProps } = props;

const client = useQueryClient();
const { namespace, name } = kubeObject.metadata;
const endpoint = useEndpoints(kubeObject._class().apiEndpoint.apiInfo, kubeObject.cluster);

return (
<MuiLink
onClick={() => {
const key = kubeObjectQueryKey({
cluster: kubeObject.cluster,
endpoint,
namespace,
name,
});
// prepopulate the query cache with existing object
client.setQueryData(key, kubeObject);
// and invalidate it (mark as stale)
// so that the latest version will be downloaded in the background
client.invalidateQueries({ queryKey: key });
}}
component={RouterLink}
to={kubeObject.getDetailsLink()}
{...otherProps}
>
{props.children || kubeObject!.getName()}
</MuiLink>
);
}

function PureLink(props: React.PropsWithChildren<LinkProps | LinkObjectProps>) {
if ((props as LinkObjectProps).kubeObject) {
const { kubeObject, ...otherProps } = props as LinkObjectProps;
return (
<MuiLink component={RouterLink} to={kubeObject!.getDetailsLink()} {...otherProps}>
{props.children || kubeObject!.getName()}
</MuiLink>
);
return <KubeObjectLink kubeObject={kubeObject!} {...otherProps} />;
}

const { routeName, params = {}, search, state, ...otherProps } = props as LinkProps;
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/components/workload/Overview.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Grid from '@mui/material/Grid';
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';
import CronJob from '../../lib/k8s/cronJob';
import DaemonSet from '../../lib/k8s/daemonSet';
import Deployment from '../../lib/k8s/deployment';
Expand All @@ -13,7 +12,7 @@ import { WorkloadClass } from '../../lib/k8s/Workload';
import { Workload } from '../../lib/k8s/Workload';
import { getReadyReplicas, getTotalReplicas } from '../../lib/util';
import Link from '../common/Link';
import { PageGrid, ResourceLink } from '../common/Resource';
import { PageGrid } from '../common/Resource';
import ResourceListView from '../common/Resource/ResourceListView';
import { SectionBox } from '../common/SectionBox';
import { WorkloadCircleChart } from './Charts';
Expand Down Expand Up @@ -44,7 +43,6 @@ export default function Overview() {
[pods, deployments, statefulSets, daemonSets, replicaSets, jobs, cronJobs]
);

const location = useLocation();
const { t } = useTranslation('glossary');

function getPods(item: Workload) {
Expand Down Expand Up @@ -130,7 +128,7 @@ export default function Overview() {
id: 'name',
label: t('translation|Name'),
getValue: item => item.metadata.name,
render: item => <ResourceLink resource={item} state={{ backLink: { ...location } }} />,
render: item => <Link kubeObject={item} />,
},
'namespace',
'cluster',
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/lib/k8s/api/v2/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ export interface QueryListResponse<DataType, ItemType, ErrorType>
clusterErrors?: Record<string, ApiError | null> | null;
}

export const kubeObjectQueryKey = ({
cluster,
endpoint,
namespace,
name,
queryParams,
}: {
cluster: string;
endpoint?: KubeObjectEndpoint | null;
namespace?: string;
name: string;
queryParams?: QueryParameters;
}) => ['object', cluster, endpoint, namespace ?? '', name, queryParams ?? {}];

/**
* Returns a single KubeObject.
*/
Expand Down Expand Up @@ -94,7 +108,8 @@ export function useKubeObject<K extends KubeObject>({
);

const queryKey = useMemo(
() => ['object', cluster, endpoint, namespace ?? '', name, cleanedUpQueryParams],
() =>
kubeObjectQueryKey({ cluster, name, namespace, endpoint, queryParams: cleanedUpQueryParams }),
[endpoint, namespace, name]
);

Expand Down

0 comments on commit 1c0e695

Please sign in to comment.