mirror of
https://github.com/nicotsx/zerobyte.git
synced 2026-06-06 15:37:22 -04:00
83 lines
3.6 KiB
TypeScript
83 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, expect, test, vi } from "vitest";
|
|
import { Scheduler } from "~/server/core/scheduler";
|
|
import { serverEvents } from "~/server/core/events";
|
|
import { config } from "~/server/core/config";
|
|
import { db } from "~/server/db/db";
|
|
import { backupsService } from "~/server/modules/backups/backups.service";
|
|
import { repositoriesService } from "~/server/modules/repositories/repositories.service";
|
|
import { notificationsService } from "~/server/modules/notifications/notifications.service";
|
|
import { volumeService } from "~/server/modules/volumes/volume.service";
|
|
import * as provisioningModule from "~/server/modules/provisioning/provisioning";
|
|
import { taskStore } from "~/server/modules/tasks/tasks.store";
|
|
import { createTestBackupSchedule } from "~/test/helpers/backup";
|
|
import { createTestRepository } from "~/test/helpers/repository";
|
|
import { createTestVolume } from "~/test/helpers/volume";
|
|
import { TEST_ORG_ID } from "~/test/helpers/organization";
|
|
|
|
const loadStartupModule = async () => {
|
|
const moduleUrl = new URL("../startup.ts", import.meta.url);
|
|
moduleUrl.searchParams.set("test", crypto.randomUUID());
|
|
return import(moduleUrl.href);
|
|
};
|
|
|
|
let originalEnableLocalAgent: boolean;
|
|
|
|
beforeEach(() => {
|
|
originalEnableLocalAgent = config.flags.enableLocalAgent;
|
|
config.flags.enableLocalAgent = true;
|
|
|
|
vi.spyOn(Scheduler, "start").mockResolvedValue();
|
|
vi.spyOn(Scheduler, "clear").mockResolvedValue();
|
|
vi.spyOn(Scheduler, "build").mockImplementation(() => ({ schedule: vi.fn() }));
|
|
vi.spyOn(provisioningModule, "syncProvisionedResources").mockResolvedValue();
|
|
vi.spyOn(backupsService, "cleanupOrphanedSchedules").mockResolvedValue({ deletedSchedules: 0 });
|
|
vi.spyOn(volumeService, "updateVolume").mockResolvedValue(undefined as never);
|
|
vi.spyOn(repositoriesService, "updateRepository").mockResolvedValue(undefined as never);
|
|
vi.spyOn(notificationsService, "updateDestination").mockResolvedValue(undefined as never);
|
|
});
|
|
|
|
afterEach(() => {
|
|
config.flags.enableLocalAgent = originalEnableLocalAgent;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
test("marks active tasks stale and keeps stuck backup schedule recovery silent", async () => {
|
|
const emitSpy = vi.spyOn(serverEvents, "emit");
|
|
const notificationSpy = vi.spyOn(notificationsService, "sendBackupNotification").mockResolvedValue();
|
|
const volume = await createTestVolume();
|
|
const repository = await createTestRepository();
|
|
const schedule = await createTestBackupSchedule({
|
|
volumeId: volume.id,
|
|
repositoryId: repository.id,
|
|
lastBackupStatus: "in_progress",
|
|
});
|
|
const task = taskStore.create({
|
|
id: "task-startup-active",
|
|
organizationId: TEST_ORG_ID,
|
|
resourceType: "backup_schedule",
|
|
resourceId: String(schedule.id),
|
|
targetAgentId: "local",
|
|
input: {
|
|
kind: "backup",
|
|
scheduleId: schedule.id,
|
|
scheduleShortId: schedule.shortId,
|
|
manual: false,
|
|
},
|
|
});
|
|
taskStore.markRunning(task.id);
|
|
|
|
const { startup } = await loadStartupModule();
|
|
|
|
await startup();
|
|
|
|
const updatedTask = await db.query.tasksTable.findFirst({ where: { id: task.id } });
|
|
const updatedSchedule = await db.query.backupSchedulesTable.findFirst({ where: { id: schedule.id } });
|
|
expect(updatedTask?.status).toBe("stale");
|
|
expect(updatedTask?.error).toBe("Zerobyte was restarted before this task completed");
|
|
expect(updatedTask?.finishedAt).toEqual(expect.any(Number));
|
|
expect(updatedSchedule?.lastBackupStatus).toBe("warning");
|
|
expect(updatedSchedule?.lastBackupError).toBe("Zerobyte was restarted during the last scheduled backup");
|
|
expect(emitSpy).not.toHaveBeenCalledWith("backup:completed", expect.anything());
|
|
expect(notificationSpy).not.toHaveBeenCalled();
|
|
});
|