refactor: improve perf by calling api in parallel in clientLoaders (#312)
* refactor: improve perf by calling api in parallel in clientLoaders * fix: dependent api calls
This commit is contained in:
parent
13428224e8
commit
f0e956783a
7 changed files with 59 additions and 25 deletions
|
|
@ -21,11 +21,13 @@ import { StatusDot } from "~/client/components/status-dot";
|
|||
import { formatDistanceToNow } from "date-fns";
|
||||
import { Link } from "react-router";
|
||||
import { cn } from "~/client/lib/utils";
|
||||
import type { GetScheduleMirrorsResponse } from "~/client/api-client";
|
||||
|
||||
type Props = {
|
||||
scheduleId: number;
|
||||
primaryRepositoryId: string;
|
||||
repositories: Repository[];
|
||||
initialData: GetScheduleMirrorsResponse;
|
||||
};
|
||||
|
||||
type MirrorAssignment = {
|
||||
|
|
@ -36,13 +38,14 @@ type MirrorAssignment = {
|
|||
lastCopyError: string | null;
|
||||
};
|
||||
|
||||
export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, repositories }: Props) => {
|
||||
export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, repositories, initialData }: Props) => {
|
||||
const [assignments, setAssignments] = useState<Map<string, MirrorAssignment>>(new Map());
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
const [isAddingNew, setIsAddingNew] = useState(false);
|
||||
|
||||
const { data: currentMirrors } = useQuery({
|
||||
...getScheduleMirrorsOptions({ path: { scheduleId: scheduleId.toString() } }),
|
||||
initialData,
|
||||
});
|
||||
|
||||
const { data: compatibility } = useQuery({
|
||||
|
|
|
|||
|
|
@ -14,10 +14,12 @@ import {
|
|||
} from "~/client/api-client/@tanstack/react-query.gen";
|
||||
import { parseError } from "~/client/lib/errors";
|
||||
import type { NotificationDestination } from "~/client/lib/types";
|
||||
import type { GetScheduleNotificationsResponse } from "~/client/api-client";
|
||||
|
||||
type Props = {
|
||||
scheduleId: number;
|
||||
destinations: NotificationDestination[];
|
||||
initialData: GetScheduleNotificationsResponse;
|
||||
};
|
||||
|
||||
type NotificationAssignment = {
|
||||
|
|
@ -28,13 +30,14 @@ type NotificationAssignment = {
|
|||
notifyOnFailure: boolean;
|
||||
};
|
||||
|
||||
export const ScheduleNotificationsConfig = ({ scheduleId, destinations }: Props) => {
|
||||
export const ScheduleNotificationsConfig = ({ scheduleId, destinations, initialData }: Props) => {
|
||||
const [assignments, setAssignments] = useState<Map<number, NotificationAssignment>>(new Map());
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
const [isAddingNew, setIsAddingNew] = useState(false);
|
||||
|
||||
const { data: currentAssignments } = useQuery({
|
||||
...getScheduleNotificationsOptions({ path: { scheduleId: scheduleId.toString() } }),
|
||||
initialData,
|
||||
});
|
||||
|
||||
const updateNotifications = useMutation({
|
||||
|
|
|
|||
|
|
@ -30,7 +30,13 @@ import { ScheduleSummary } from "../components/schedule-summary";
|
|||
import type { Route } from "./+types/backup-details";
|
||||
import { SnapshotFileBrowser } from "../components/snapshot-file-browser";
|
||||
import { SnapshotTimeline } from "../components/snapshot-timeline";
|
||||
import { getBackupSchedule, listNotificationDestinations, listRepositories } from "~/client/api-client";
|
||||
import {
|
||||
getBackupSchedule,
|
||||
getScheduleMirrors,
|
||||
getScheduleNotifications,
|
||||
listNotificationDestinations,
|
||||
listRepositories,
|
||||
} from "~/client/api-client";
|
||||
import { ScheduleNotificationsConfig } from "../components/schedule-notifications-config";
|
||||
import { ScheduleMirrorsConfig } from "../components/schedule-mirrors-config";
|
||||
import { cn } from "~/client/lib/utils";
|
||||
|
|
@ -53,13 +59,23 @@ export function meta(_: Route.MetaArgs) {
|
|||
}
|
||||
|
||||
export const clientLoader = async ({ params }: Route.LoaderArgs) => {
|
||||
const schedule = await getBackupSchedule({ path: { scheduleId: params.id } });
|
||||
const notifs = await listNotificationDestinations();
|
||||
const repos = await listRepositories();
|
||||
const [schedule, notifs, repos, scheduleNotifs, mirrors] = await Promise.all([
|
||||
getBackupSchedule({ path: { scheduleId: params.id } }),
|
||||
listNotificationDestinations(),
|
||||
listRepositories(),
|
||||
getScheduleNotifications({ path: { scheduleId: params.id } }),
|
||||
getScheduleMirrors({ path: { scheduleId: params.id } }),
|
||||
]);
|
||||
|
||||
if (!schedule.data) return redirect("/backups");
|
||||
|
||||
return { schedule: schedule.data, notifs: notifs.data, repos: repos.data };
|
||||
return {
|
||||
schedule: schedule.data,
|
||||
notifs: notifs.data,
|
||||
repos: repos.data,
|
||||
scheduleNotifs: scheduleNotifs.data,
|
||||
scheduleMirrors: mirrors.data,
|
||||
};
|
||||
};
|
||||
|
||||
export default function ScheduleDetailsPage({ params, loaderData }: Route.ComponentProps) {
|
||||
|
|
@ -240,13 +256,18 @@ export default function ScheduleDetailsPage({ params, loaderData }: Route.Compon
|
|||
schedule={schedule}
|
||||
/>
|
||||
<div className={cn({ hidden: !loaderData.notifs?.length })}>
|
||||
<ScheduleNotificationsConfig scheduleId={schedule.id} destinations={loaderData.notifs ?? []} />
|
||||
<ScheduleNotificationsConfig
|
||||
scheduleId={schedule.id}
|
||||
destinations={loaderData.notifs ?? []}
|
||||
initialData={loaderData.scheduleNotifs ?? []}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn({ hidden: !loaderData.repos?.length || loaderData.repos.length < 2 })}>
|
||||
<ScheduleMirrorsConfig
|
||||
scheduleId={schedule.id}
|
||||
primaryRepositoryId={schedule.repositoryId}
|
||||
repositories={loaderData.repos ?? []}
|
||||
initialData={loaderData.scheduleMirrors ?? []}
|
||||
/>
|
||||
</div>
|
||||
<SnapshotTimeline
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ export function meta(_: Route.MetaArgs) {
|
|||
}
|
||||
|
||||
export const clientLoader = async () => {
|
||||
const volumes = await listVolumes();
|
||||
const repositories = await listRepositories();
|
||||
const [volumes, repositories] = await Promise.all([listVolumes(), listRepositories()]);
|
||||
|
||||
if (volumes.data && repositories.data) return { volumes: volumes.data, repositories: repositories.data };
|
||||
return { volumes: [], repositories: [] };
|
||||
|
|
|
|||
|
|
@ -24,15 +24,20 @@ export function meta({ params }: Route.MetaArgs) {
|
|||
|
||||
export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => {
|
||||
const schedule = await getBackupSchedule({ path: { scheduleId: params.id } });
|
||||
|
||||
if (!schedule.data) return redirect("/backups");
|
||||
|
||||
const repositoryId = schedule.data.repository.id;
|
||||
const snapshot = await getSnapshotDetails({
|
||||
path: { id: repositoryId, snapshotId: params.snapshotId },
|
||||
});
|
||||
if (!snapshot.data) return redirect(`/backups/${params.id}`);
|
||||
const [snapshot, repository] = await Promise.all([
|
||||
getSnapshotDetails({
|
||||
path: {
|
||||
id: schedule.data.repositoryId,
|
||||
snapshotId: params.snapshotId,
|
||||
},
|
||||
}),
|
||||
getRepository({ path: { id: schedule.data.repositoryId } }),
|
||||
]);
|
||||
|
||||
const repository = await getRepository({ path: { id: repositoryId } });
|
||||
if (!snapshot.data) return redirect(`/backups/${params.id}`);
|
||||
if (!repository.data) return redirect(`/backups/${params.id}`);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ export function meta({ params }: Route.MetaArgs) {
|
|||
}
|
||||
|
||||
export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => {
|
||||
const snapshot = await getSnapshotDetails({
|
||||
path: { id: params.id, snapshotId: params.snapshotId },
|
||||
});
|
||||
if (!snapshot.data) return redirect("/repositories");
|
||||
const [snapshot, repository] = await Promise.all([
|
||||
getSnapshotDetails({ path: { id: params.id, snapshotId: params.snapshotId } }),
|
||||
getRepository({ path: { id: params.id } }),
|
||||
]);
|
||||
|
||||
const repository = await getRepository({ path: { id: params.id } });
|
||||
if (!snapshot.data) return redirect("/repositories");
|
||||
if (!repository.data) return redirect(`/repositories`);
|
||||
|
||||
return { snapshot: snapshot.data, id: params.id, repository: repository.data, snapshotId: params.snapshotId };
|
||||
|
|
|
|||
|
|
@ -26,11 +26,14 @@ export function meta({ params }: Route.MetaArgs) {
|
|||
}
|
||||
|
||||
export const clientLoader = async ({ params }: Route.ClientLoaderArgs) => {
|
||||
const snapshot = getSnapshotDetails({
|
||||
path: { id: params.id, snapshotId: params.snapshotId },
|
||||
});
|
||||
const [snapshot, repository] = await Promise.all([
|
||||
getSnapshotDetails({
|
||||
path: { id: params.id, snapshotId: params.snapshotId },
|
||||
}),
|
||||
getRepository({ path: { id: params.id } }),
|
||||
]);
|
||||
|
||||
const repository = await getRepository({ path: { id: params.id } });
|
||||
if (!snapshot.data) return redirect(`/repositories/${params.id}`);
|
||||
if (!repository.data) return redirect("/repositories");
|
||||
|
||||
return { snapshot: snapshot, repository: repository.data };
|
||||
|
|
|
|||
Loading…
Reference in a new issue