fix: strengthen live recovery and support diagnostics
Apply account and key changes to active queues without a restart and isolate provider attempt cancellation so fallback accounts remain usable. Preserve pause ownership, bound persisted HTTP 416 recovery, reconcile resets with authoritative state, and stabilize package ordering and live update cadence. Correlate rotation, conversion, resume, disk, queue-control, clipboard, and support-export events while redacting sensitive data at every persistent boundary and again in generated bundles. Release as v2.0.31 with updated English documentation and regression coverage.
This commit is contained in:
+64
-5
@@ -954,7 +954,7 @@ describe("settings storage", () => {
|
||||
expect(loaded.packageOrder).toEqual(empty.packageOrder);
|
||||
});
|
||||
|
||||
it("loads backup session when primary session is corrupted", () => {
|
||||
it("loads backup session when primary session is corrupted", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rd-store-"));
|
||||
tempDirs.push(dir);
|
||||
const paths = createStoragePaths(dir);
|
||||
@@ -1005,10 +1005,69 @@ describe("settings storage", () => {
|
||||
expect(loaded.items["item-backup"]?.fileName).toBe("backup-file.rar");
|
||||
|
||||
const restoredPrimary = JSON.parse(fs.readFileSync(paths.sessionFile, "utf8")) as { packages?: Record<string, unknown> };
|
||||
expect(restoredPrimary.packages && "pkg-backup" in restoredPrimary.packages).toBe(true);
|
||||
});
|
||||
|
||||
it("returns defaults when config file contains invalid JSON", () => {
|
||||
expect(restoredPrimary.packages && "pkg-backup" in restoredPrimary.packages).toBe(true);
|
||||
});
|
||||
|
||||
it("preserves resume recovery state across a session save and reload", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rd-store-"));
|
||||
tempDirs.push(dir);
|
||||
const paths = createStoragePaths(dir);
|
||||
const session = emptySession();
|
||||
const now = Date.now();
|
||||
const outputDir = path.join(dir, "out");
|
||||
const itemId = "item-resume";
|
||||
session.packageOrder = ["pkg-resume"];
|
||||
session.packages["pkg-resume"] = {
|
||||
id: "pkg-resume",
|
||||
name: "Resume Package",
|
||||
outputDir,
|
||||
extractDir: path.join(dir, "extract"),
|
||||
status: "queued",
|
||||
itemIds: [itemId],
|
||||
cancelled: false,
|
||||
enabled: true,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
};
|
||||
session.items[itemId] = {
|
||||
id: itemId,
|
||||
packageId: "pkg-resume",
|
||||
url: "https://example.com/resume-file",
|
||||
provider: "megadebrid-web",
|
||||
status: "queued",
|
||||
retries: 2,
|
||||
speedBps: 0,
|
||||
downloadedBytes: 8192,
|
||||
totalBytes: 16384,
|
||||
progressPercent: 50,
|
||||
fileName: "resume-file.bin",
|
||||
targetPath: path.join(outputDir, "resume-file.bin"),
|
||||
resumable: true,
|
||||
attempts: 3,
|
||||
lastError: "",
|
||||
fullStatus: "Resume-Link erneuern",
|
||||
resumeLinkRenewalFailures: 4,
|
||||
resumeHardResetUsed: true,
|
||||
resumeResetPending: true,
|
||||
http416FreshRestarts: 2,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
};
|
||||
|
||||
saveSession(paths, session);
|
||||
const loaded = loadSession(paths);
|
||||
|
||||
expect(loaded.items[itemId]).toEqual(expect.objectContaining({
|
||||
downloadedBytes: 8192,
|
||||
totalBytes: 16384,
|
||||
resumeLinkRenewalFailures: 4,
|
||||
resumeHardResetUsed: true,
|
||||
resumeResetPending: true,
|
||||
http416FreshRestarts: 2
|
||||
}));
|
||||
});
|
||||
|
||||
it("returns defaults when config file contains invalid JSON", () => {
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rd-store-"));
|
||||
tempDirs.push(dir);
|
||||
const paths = createStoragePaths(dir);
|
||||
|
||||
Reference in New Issue
Block a user