refactor: pr feedbacks

This commit is contained in:
Nicolas Meienberger 2026-02-12 18:30:21 +01:00
parent d5284d9450
commit 7746cf3608
7 changed files with 67 additions and 19 deletions

View file

@ -1,4 +1,4 @@
import { useEffect, useRef } from "react";
import { useCallback, useEffect, useRef } from "react";
import { useQueryClient } from "@tanstack/react-query";
import type {
BackupCompletedEventDto,
@ -205,7 +205,7 @@ export function useServerEvents() {
};
}, [queryClient]);
const addEventListener = (event: ServerEventType, handler: EventHandler) => {
const addEventListener = useCallback((event: ServerEventType, handler: EventHandler) => {
if (!handlersRef.current.has(event)) {
handlersRef.current.set(event, new Set());
}
@ -214,7 +214,7 @@ export function useServerEvents() {
return () => {
handlersRef.current.get(event)?.delete(handler);
};
};
}, []);
return { addEventListener };
}

View file

@ -356,7 +356,7 @@ export const ScheduleMirrorsConfig = ({ scheduleId, primaryRepositoryId, reposit
<StatusDot
variant={getStatusVariant(assignment.lastCopyStatus)}
label={getStatusLabel(assignment)}
animated={isSyncing(assignment) ? true : undefined}
animated={isSyncing(assignment)}
/>
<span className="text-sm text-muted-foreground">{getLabel(assignment)}</span>
</div>

View file

@ -49,8 +49,25 @@ export function BackupsPage() {
if (over && active.id !== over.id) {
setLocalItems((currentItems) => {
const baseItems = currentItems ?? schedules?.map((s) => s.id) ?? [];
const oldIndex = baseItems.indexOf(active.id as number);
const newIndex = baseItems.indexOf(over.id as number);
const activeId = active.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);
reorderMutation.mutate({ body: { scheduleIds: newItems } });

View file

@ -6,13 +6,6 @@ import { RepositoryInfoTabContent } from "../tabs/info";
import { RepositorySnapshotsTabContent } from "../tabs/snapshots";
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 }) {
const navigate = useNavigate();
const { tab } = useSearch({ from: "/(dashboard)/repositories/$repositoryId" });

View file

@ -296,6 +296,37 @@ describe("mirror operations", () => {
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 () => {
// arrange
const volume = await createTestVolume();

View file

@ -367,7 +367,6 @@ const copyToSingleMirror = async (
schedule: BackupSchedule,
sourceRepository: Repository,
mirror: {
id: number;
repositoryId: string;
repository: Repository;
},
@ -384,7 +383,7 @@ const copyToSingleMirror = async (
repositoryName: mirror.repository.name,
});
await mirrorQueries.updateStatus(mirror.id, {
await mirrorQueries.updateStatus(scheduleId, mirror.repositoryId, {
lastCopyStatus: "in_progress",
lastCopyError: null,
});
@ -408,7 +407,7 @@ const copyToSingleMirror = async (
});
}
await mirrorQueries.updateStatus(mirror.id, {
await mirrorQueries.updateStatus(scheduleId, mirror.repositoryId, {
lastCopyAt: Date.now(),
lastCopyStatus: "success",
lastCopyError: null,
@ -427,7 +426,7 @@ const copyToSingleMirror = async (
const errorMessage = toMessage(error);
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(),
lastCopyStatus: "error",
lastCopyError: errorMessage,

View file

@ -59,8 +59,16 @@ export const mirrorQueries = {
});
},
updateStatus: async (mirrorId: number, status: MirrorStatusUpdate) => {
return db.update(backupScheduleMirrorsTable).set(status).where(eq(backupScheduleMirrorsTable.id, mirrorId));
updateStatus: async (scheduleId: number, repositoryId: string, status: MirrorStatusUpdate) => {
return db
.update(backupScheduleMirrorsTable)
.set(status)
.where(
and(
eq(backupScheduleMirrorsTable.scheduleId, scheduleId),
eq(backupScheduleMirrorsTable.repositoryId, repositoryId),
),
);
},
};