fix: align live speed and split package reset

This commit is contained in:
Sucukdeluxe
2026-08-31 18:21:58 +02:00
parent 217b7b026e
commit f14d166898
9 changed files with 270 additions and 85 deletions
+97
View File
@@ -49,6 +49,33 @@ describe("runWithLimitedConcurrency", () => {
});
describe("download live update cadence", () => {
it("uses the same rolling traffic window for item and package speed", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-speed-window-"));
tempDirs.push(root);
const manager = new DownloadManager(
defaultSettings(),
emptySession(),
createStoragePaths(path.join(root, "state"))
);
manager.addPackages([{ name: "speed", links: ["https://dummy/speed.bin"] }]);
const initial = manager.getSnapshot();
const packageId = initial.session.packageOrder[0];
const itemId = initial.session.packages[packageId].itemIds[0];
const internal = manager as any;
internal.session.running = true;
internal.session.paused = false;
internal.session.packages[packageId].status = "downloading";
internal.session.items[itemId].status = "downloading";
internal.session.items[itemId].speedBps = 47_870_000;
internal.recordSpeed(18_550_000, packageId, itemId);
const snapshot = manager.getSnapshot();
expect(snapshot.packageSpeedBps[packageId]).toBe(18_550_000);
expect(snapshot.session.items[itemId].speedBps).toBe(snapshot.packageSpeedBps[packageId]);
expect(internal.session.items[itemId].speedBps).toBe(47_870_000);
});
it.each([69, 661, 2_470])("emits a running queue snapshot no sooner than 750 ms for %i items", async (itemCount) => {
vi.useFakeTimers();
try {
@@ -8858,6 +8885,76 @@ describe("download manager", () => {
}
});
it("resets only selected package errors and preserves successful downloaded files", async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-selective-package-reset-"));
tempDirs.push(root);
const session = emptySession();
const packageId = "selective-reset-package";
const outputDir = path.join(root, "downloads", "selective-reset");
const createdAt = Date.now();
const itemIds = ["successful", "download-error", "extract-error"];
fs.mkdirSync(outputDir, { recursive: true });
session.packageOrder = [packageId];
session.packages[packageId] = {
id: packageId,
name: "selective-reset",
outputDir,
extractDir: path.join(root, "extract", "selective-reset"),
status: "failed",
itemIds,
cancelled: false,
enabled: true,
createdAt,
updatedAt: createdAt
};
for (const itemId of itemIds) {
const targetPath = path.join(outputDir, `${itemId}.rar`);
fs.writeFileSync(targetPath, itemId);
session.items[itemId] = {
id: itemId,
packageId,
url: `https://dummy/${itemId}`,
provider: "realdebrid",
status: itemId === "download-error" ? "failed" : "completed",
retries: 0,
speedBps: 0,
downloadedBytes: itemId.length,
totalBytes: itemId.length,
progressPercent: 100,
fileName: `${itemId}.rar`,
targetPath,
resumable: true,
attempts: 1,
lastError: itemId === "successful" ? "" : "Fehler",
fullStatus: itemId === "successful" ? "Entpackt" : itemId === "extract-error" ? "Entpack-Fehler: CRCERROR" : "Fehlgeschlagen",
createdAt,
updatedAt: createdAt
};
}
const manager = new DownloadManager(
defaultSettings(),
session,
createStoragePaths(path.join(root, "state"))
);
await manager.resetItems(["download-error", "extract-error"]);
const snapshot = manager.getSnapshot().session;
expect(snapshot.items.successful.status).toBe("completed");
expect(snapshot.items.successful.targetPath).toBe(path.join(outputDir, "successful.rar"));
expect(fs.existsSync(snapshot.items.successful.targetPath)).toBe(true);
for (const itemId of ["download-error", "extract-error"]) {
expect(snapshot.items[itemId]).toEqual(expect.objectContaining({
status: "queued",
downloadedBytes: 0,
totalBytes: null,
targetPath: "",
fullStatus: "Wartet"
}));
expect(fs.existsSync(path.join(outputDir, `${itemId}.rar`))).toBe(false);
}
});
it("does not freeze the scheduler when a reset item's old task is parked in a non-abort-observing await", async () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "rd-dm-"));
tempDirs.push(root);