refactor: pr feedbacks
This commit is contained in:
parent
d5284d9450
commit
7746cf3608
7 changed files with 67 additions and 19 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
import { useQueryClient } from "@tanstack/react-query";
|
import { useQueryClient } from "@tanstack/react-query";
|
||||||
import type {
|
import type {
|
||||||
BackupCompletedEventDto,
|
BackupCompletedEventDto,
|
||||||
|
|
@ -205,7 +205,7 @@ export function useServerEvents() {
|
||||||
};
|
};
|
||||||
}, [queryClient]);
|
}, [queryClient]);
|
||||||
|
|
||||||
const addEventListener = (event: ServerEventType, handler: EventHandler) => {
|
const addEventListener = useCallback((event: ServerEventType, handler: EventHandler) => {
|
||||||
if (!handlersRef.current.has(event)) {
|
if (!handlersRef.current.has(event)) {
|
||||||
handlersRef.current.set(event, new Set());
|
handlersRef.current.set(event, new Set());
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +214,7 @@ export function useServerEvents() {
|
||||||
return () => {
|
return () => {
|
||||||
handlersRef.current.get(event)?.delete(handler);
|
handlersRef.current.get(event)?.delete(handler);
|
||||||
};
|
};
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
return { addEventListener };
|
return { addEventListener };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
|
||||||
<StatusDot
|
<StatusDot
|
||||||
variant={getStatusVariant(assignment.lastCopyStatus)}
|
variant={getStatusVariant(assignment.lastCopyStatus)}
|
||||||
label={getStatusLabel(assignment)}
|
label={getStatusLabel(assignment)}
|
||||||
animated={isSyncing(assignment) ? true : undefined}
|
animated={isSyncing(assignment)}
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-muted-foreground">{getLabel(assignment)}</span>
|
<span className="text-sm text-muted-foreground">{getLabel(assignment)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,25 @@ export function BackupsPage() {
|
||||||
if (over && active.id !== over.id) {
|
if (over && active.id !== over.id) {
|
||||||
setLocalItems((currentItems) => {
|
setLocalItems((currentItems) => {
|
||||||
const baseItems = currentItems ?? schedules?.map((s) => s.id) ?? [];
|
const baseItems = currentItems ?? schedules?.map((s) => s.id) ?? [];
|
||||||
const oldIndex = baseItems.indexOf(active.id as number);
|
const activeId = active.id as number;
|
||||||
const newIndex = baseItems.indexOf(over.id as number);
|
const overId = over.id as number;
|
||||||
|
let oldIndex = baseItems.indexOf(activeId);
|
||||||
|
let newIndex = baseItems.indexOf(overId);
|
||||||
|
|
||||||
|
if (oldIndex === -1 || newIndex === -1) {
|
||||||
|
const freshItems = schedules?.map((s) => s.id) ?? [];
|
||||||
|
oldIndex = freshItems.indexOf(activeId);
|
||||||
|
newIndex = freshItems.indexOf(overId);
|
||||||
|
|
||||||
|
if (oldIndex === -1 || newIndex === -1) {
|
||||||
|
return currentItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newItems = arrayMove(freshItems, oldIndex, newIndex);
|
||||||
|
reorderMutation.mutate({ body: { scheduleIds: newItems } });
|
||||||
|
return newItems;
|
||||||
|
}
|
||||||
|
|
||||||
const newItems = arrayMove(baseItems, oldIndex, newIndex);
|
const newItems = arrayMove(baseItems, oldIndex, newIndex);
|
||||||
reorderMutation.mutate({ body: { scheduleIds: newItems } });
|
reorderMutation.mutate({ body: { scheduleIds: newItems } });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,6 @@ import { RepositoryInfoTabContent } from "../tabs/info";
|
||||||
import { RepositorySnapshotsTabContent } from "../tabs/snapshots";
|
import { RepositorySnapshotsTabContent } from "../tabs/snapshots";
|
||||||
import { useNavigate, useSearch } from "@tanstack/react-router";
|
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||||
|
|
||||||
export const handle = {
|
|
||||||
breadcrumb: (match: Route.MetaArgs) => [
|
|
||||||
{ label: "Repositories", href: "/repositories" },
|
|
||||||
{ label: match.loaderData?.name || match.params.id },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RepositoryDetailsPage({ repositoryId }: { repositoryId: string }) {
|
export default function RepositoryDetailsPage({ repositoryId }: { repositoryId: string }) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { tab } = useSearch({ from: "/(dashboard)/repositories/$repositoryId" });
|
const { tab } = useSearch({ from: "/(dashboard)/repositories/$repositoryId" });
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,37 @@ describe("mirror operations", () => {
|
||||||
expect(updatedMirror?.lastCopyAt).not.toBeNull();
|
expect(updatedMirror?.lastCopyAt).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should finalize mirror status when mirror settings are updated during copy", async () => {
|
||||||
|
// arrange
|
||||||
|
const volume = await createTestVolume();
|
||||||
|
const sourceRepository = await createTestRepository();
|
||||||
|
const mirrorRepository = await createTestRepository();
|
||||||
|
const schedule = await createTestBackupSchedule({
|
||||||
|
volumeId: volume.id,
|
||||||
|
repositoryId: sourceRepository.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const originalMirror = await createTestBackupScheduleMirror(schedule.id, mirrorRepository.id);
|
||||||
|
|
||||||
|
resticCopyMock.mockImplementationOnce(async () => {
|
||||||
|
await backupsService.updateMirrors(schedule.id, {
|
||||||
|
mirrors: [{ repositoryId: mirrorRepository.id, enabled: true }],
|
||||||
|
});
|
||||||
|
return { success: true, output: "" };
|
||||||
|
});
|
||||||
|
|
||||||
|
// act
|
||||||
|
await backupsExecutionService.copyToMirrors(schedule.id, sourceRepository, null);
|
||||||
|
|
||||||
|
// assert
|
||||||
|
const mirrors = await backupsService.getMirrors(schedule.id);
|
||||||
|
expect(mirrors).toHaveLength(1);
|
||||||
|
expect(mirrors[0]?.id).not.toBe(originalMirror.id);
|
||||||
|
expect(mirrors[0]?.lastCopyStatus).toBe("success");
|
||||||
|
expect(mirrors[0]?.lastCopyError).toBeNull();
|
||||||
|
expect(mirrors[0]?.lastCopyAt).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
test("should update mirror status on failure", async () => {
|
test("should update mirror status on failure", async () => {
|
||||||
// arrange
|
// arrange
|
||||||
const volume = await createTestVolume();
|
const volume = await createTestVolume();
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,6 @@ const copyToSingleMirror = async (
|
||||||
schedule: BackupSchedule,
|
schedule: BackupSchedule,
|
||||||
sourceRepository: Repository,
|
sourceRepository: Repository,
|
||||||
mirror: {
|
mirror: {
|
||||||
id: number;
|
|
||||||
repositoryId: string;
|
repositoryId: string;
|
||||||
repository: Repository;
|
repository: Repository;
|
||||||
},
|
},
|
||||||
|
|
@ -384,7 +383,7 @@ const copyToSingleMirror = async (
|
||||||
repositoryName: mirror.repository.name,
|
repositoryName: mirror.repository.name,
|
||||||
});
|
});
|
||||||
|
|
||||||
await mirrorQueries.updateStatus(mirror.id, {
|
await mirrorQueries.updateStatus(scheduleId, mirror.repositoryId, {
|
||||||
lastCopyStatus: "in_progress",
|
lastCopyStatus: "in_progress",
|
||||||
lastCopyError: null,
|
lastCopyError: null,
|
||||||
});
|
});
|
||||||
|
|
@ -408,7 +407,7 @@ const copyToSingleMirror = async (
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await mirrorQueries.updateStatus(mirror.id, {
|
await mirrorQueries.updateStatus(scheduleId, mirror.repositoryId, {
|
||||||
lastCopyAt: Date.now(),
|
lastCopyAt: Date.now(),
|
||||||
lastCopyStatus: "success",
|
lastCopyStatus: "success",
|
||||||
lastCopyError: null,
|
lastCopyError: null,
|
||||||
|
|
@ -427,7 +426,7 @@ const copyToSingleMirror = async (
|
||||||
const errorMessage = toMessage(error);
|
const errorMessage = toMessage(error);
|
||||||
logger.error(`[Background] Failed to copy to mirror repository ${mirror.repository.name}: ${errorMessage}`);
|
logger.error(`[Background] Failed to copy to mirror repository ${mirror.repository.name}: ${errorMessage}`);
|
||||||
|
|
||||||
await mirrorQueries.updateStatus(mirror.id, {
|
await mirrorQueries.updateStatus(scheduleId, mirror.repositoryId, {
|
||||||
lastCopyAt: Date.now(),
|
lastCopyAt: Date.now(),
|
||||||
lastCopyStatus: "error",
|
lastCopyStatus: "error",
|
||||||
lastCopyError: errorMessage,
|
lastCopyError: errorMessage,
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,16 @@ export const mirrorQueries = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
updateStatus: async (mirrorId: number, status: MirrorStatusUpdate) => {
|
updateStatus: async (scheduleId: number, repositoryId: string, status: MirrorStatusUpdate) => {
|
||||||
return db.update(backupScheduleMirrorsTable).set(status).where(eq(backupScheduleMirrorsTable.id, mirrorId));
|
return db
|
||||||
|
.update(backupScheduleMirrorsTable)
|
||||||
|
.set(status)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(backupScheduleMirrorsTable.scheduleId, scheduleId),
|
||||||
|
eq(backupScheduleMirrorsTable.repositoryId, repositoryId),
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue