fix(history): preserve legacy package telemetry
This commit is contained in:
@@ -58,8 +58,8 @@ function getFailure(
|
|||||||
return { failurePhase: "extract", errorCategory: failedArchive.errorCategory };
|
return { failurePhase: "extract", errorCategory: failedArchive.errorCategory };
|
||||||
}
|
}
|
||||||
const downloadError = downloadErrors.find(Boolean);
|
const downloadError = downloadErrors.find(Boolean);
|
||||||
if (downloadError) {
|
if (downloadErrors.length > 0) {
|
||||||
return { failurePhase: "download", errorCategory: downloadError };
|
return { failurePhase: "download", errorCategory: downloadError || "download" };
|
||||||
}
|
}
|
||||||
return { failurePhase: null, errorCategory: "" };
|
return { failurePhase: null, errorCategory: "" };
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ export function finalizePackageResult(telemetry: PackageTelemetry): PackageResul
|
|||||||
const cancelledFiles = cancelledDownloads + postProcessCancellations;
|
const cancelledFiles = cancelledDownloads + postProcessCancellations;
|
||||||
const successfulFiles = Math.max(0, completedDownloads - postProcessFailures - postProcessCancellations);
|
const successfulFiles = Math.max(0, completedDownloads - postProcessFailures - postProcessCancellations);
|
||||||
const startedAt = finiteNonNegative(packageEntry.downloadStartedAt);
|
const startedAt = finiteNonNegative(packageEntry.downloadStartedAt);
|
||||||
const downloadEndedAt = finiteNonNegative(packageEntry.downloadEndedAt ?? packageEntry.downloadCompletedAt);
|
const downloadEndedAt = finiteNonNegative(packageEntry.downloadEndedAt) || finiteNonNegative(packageEntry.downloadCompletedAt);
|
||||||
const postProcessStartedAt = finiteNonNegative(packageEntry.postProcessStartedAt);
|
const postProcessStartedAt = finiteNonNegative(packageEntry.postProcessStartedAt);
|
||||||
const postProcessCompletedAt = finiteNonNegative(packageEntry.postProcessCompletedAt);
|
const postProcessCompletedAt = finiteNonNegative(packageEntry.postProcessCompletedAt);
|
||||||
const completedAt = finiteNonNegative(packageEntry.terminalAt);
|
const completedAt = finiteNonNegative(packageEntry.terminalAt);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
durationSecondsBetween,
|
durationSecondsBetween,
|
||||||
finalizePackageResult
|
finalizePackageResult
|
||||||
} from "../src/main/package-telemetry";
|
} from "../src/main/package-telemetry";
|
||||||
|
import { normalizeLoadedSession } from "../src/main/storage";
|
||||||
|
|
||||||
function packageEntry(overrides: Partial<PackageEntry> = {}): PackageEntry {
|
function packageEntry(overrides: Partial<PackageEntry> = {}): PackageEntry {
|
||||||
return {
|
return {
|
||||||
@@ -173,6 +174,21 @@ describe("package lifecycle telemetry", () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("classifies a failed download without error text as a download-phase failure", () => {
|
||||||
|
const item = { ...downloadItem("item-1", "failed"), lastError: "", fullStatus: "" };
|
||||||
|
const result = finalizePackageResult(telemetry({
|
||||||
|
package: packageEntry({ status: "failed", itemIds: [item.id] }),
|
||||||
|
items: [item]
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(result).toEqual(expect.objectContaining({
|
||||||
|
status: "failed",
|
||||||
|
failedFiles: 1,
|
||||||
|
failurePhase: "download",
|
||||||
|
errorCategory: "download"
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
it("classifies a package with only cancelled work as cancelled", () => {
|
it("classifies a package with only cancelled work as cancelled", () => {
|
||||||
const item = downloadItem("item-1", "cancelled");
|
const item = downloadItem("item-1", "cancelled");
|
||||||
const result = finalizePackageResult(telemetry({
|
const result = finalizePackageResult(telemetry({
|
||||||
@@ -211,6 +227,43 @@ describe("package lifecycle telemetry", () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("retains legacy download timing after session normalization", () => {
|
||||||
|
const item = { ...downloadItem("item-1"), downloadedBytes: 240_000, totalBytes: 240_000 };
|
||||||
|
const legacyPackage = packageEntry({
|
||||||
|
itemIds: [item.id],
|
||||||
|
downloadStartedAt: 1_000,
|
||||||
|
downloadCompletedAt: 121_000,
|
||||||
|
terminalAt: 121_000,
|
||||||
|
updatedAt: 121_000
|
||||||
|
});
|
||||||
|
delete legacyPackage.downloadEndedAt;
|
||||||
|
const normalized = normalizeLoadedSession({
|
||||||
|
version: 2,
|
||||||
|
packageOrder: [legacyPackage.id],
|
||||||
|
packages: { [legacyPackage.id]: legacyPackage },
|
||||||
|
items: { [item.id]: item },
|
||||||
|
runStartedAt: 1_000,
|
||||||
|
totalDownloadedBytes: 240_000,
|
||||||
|
summaryText: "",
|
||||||
|
reconnectUntil: 0,
|
||||||
|
reconnectReason: "",
|
||||||
|
paused: false,
|
||||||
|
running: false,
|
||||||
|
updatedAt: 121_000
|
||||||
|
});
|
||||||
|
const normalizedPackage = normalized.packages[legacyPackage.id];
|
||||||
|
const result = finalizePackageResult({
|
||||||
|
package: normalizedPackage,
|
||||||
|
items: normalizedPackage.itemIds.map((itemId) => normalized.items[itemId])
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toEqual(expect.objectContaining({
|
||||||
|
downloadEndedAt: 121_000,
|
||||||
|
downloadDurationSeconds: 120,
|
||||||
|
averageDownloadSpeedBps: 2_000
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
it("uses cleanup, remux, extract, and download as deterministic failure precedence", () => {
|
it("uses cleanup, remux, extract, and download as deterministic failure precedence", () => {
|
||||||
const failedItem = downloadItem("item-1", "failed");
|
const failedItem = downloadItem("item-1", "failed");
|
||||||
const failedArchive = archiveOperation({ status: "failed", errorCategory: "archive-error" });
|
const failedArchive = archiveOperation({ status: "failed", errorCategory: "archive-error" });
|
||||||
|
|||||||
Reference in New Issue
Block a user