feat(history): complete package lifecycle telemetry
Persist separate download, extraction, remux, post-processing, and total durations together with accurate file, byte, archive, part, output, and phase failure results. Keep download item counts independent from extraction and remux outcomes, distinguish partial and cancelled packages, and expose additive failure counters and fixed categories in history and Discord notifications. Track archive operations across parallel work, aborts, restarts, nested multipart sets, and skipped split files while deriving generation outputs from privacy-safe signatures and merging overlapping extraction intervals.
This commit is contained in:
@@ -59,8 +59,10 @@ const filterItems: Array<{ id: HistoryFilter; label: string }> = [
|
||||
{ id: "today", label: "Heute" },
|
||||
{ id: "week", label: "Letzte 7 Tage" },
|
||||
{ id: "older", label: "Älter" },
|
||||
{ id: "completed", label: "Fertig" },
|
||||
{ id: "deleted", label: "Gelöscht" },
|
||||
{ id: "completed", label: "Fertig" },
|
||||
{ id: "partial", label: "Teilweise" },
|
||||
{ id: "cancelled", label: "Abgebrochen" },
|
||||
{ id: "deleted", label: "Gelöscht" },
|
||||
{ id: "failed", label: "Fehlgeschlagen" }
|
||||
];
|
||||
|
||||
@@ -205,6 +207,8 @@ function HistoryRowDetails({
|
||||
<div><dt>Erfolgreich / Fehlgeschlagen / Abgebrochen</dt><dd>{row.successfulFiles ?? 0} / {row.failedFiles ?? 0} / {row.cancelledFiles ?? 0}</dd></div>
|
||||
<div><dt>Archive / Parts / Ausgaben</dt><dd>{row.archiveCount ?? 0} / {row.partCount ?? 0} / {row.outputCount ?? 0}</dd></div>
|
||||
<div><dt>Fehlerphase</dt><dd>{row.failurePhaseLabel}</dd></div>
|
||||
<div><dt>Fehlerkategorie</dt><dd>{row.errorCategory || "—"}</dd></div>
|
||||
<div><dt>Download / Offline / Entpacken / Remux / Cleanup / Nachbearbeitung</dt><dd>{row.failureCountsLabel}</dd></div>
|
||||
</>
|
||||
) : (
|
||||
<div><dt>Downloaddauer (Altbestand)</dt><dd>{row.durationLabel}</dd></div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { DebridProvider, HistoryEntry } from "../../../shared/types";
|
||||
|
||||
export type HistoryFilter = "all" | "today" | "week" | "older" | "completed" | "deleted" | "failed";
|
||||
export type HistoryFilter = "all" | "today" | "week" | "older" | "completed" | "partial" | "failed" | "cancelled" | "deleted";
|
||||
export type HistoryViewStatus = HistoryEntry["status"] | "failed";
|
||||
export type HistoryViewEntry = Omit<HistoryEntry, "status"> & { status: HistoryViewStatus };
|
||||
|
||||
@@ -23,6 +23,7 @@ export interface HistoryRow extends HistoryViewEntry {
|
||||
postProcessDurationLabel: string;
|
||||
totalDurationLabel: string;
|
||||
failurePhaseLabel: string;
|
||||
failureCountsLabel: string;
|
||||
}
|
||||
|
||||
export interface HistoryFilterCounts {
|
||||
@@ -31,6 +32,8 @@ export interface HistoryFilterCounts {
|
||||
week: number;
|
||||
older: number;
|
||||
completed: number;
|
||||
partial: number;
|
||||
cancelled: number;
|
||||
deleted: number;
|
||||
failed: number;
|
||||
}
|
||||
@@ -178,9 +181,24 @@ function failurePhaseLabel(entry: HistoryViewEntry): string {
|
||||
if (entry.failurePhase === "extract") return "Entpacken";
|
||||
if (entry.failurePhase === "remux") return "Remux";
|
||||
if (entry.failurePhase === "cleanup") return "Aufräumen";
|
||||
if (entry.failurePhase === "postprocess") return "Nachbearbeitung";
|
||||
return "—";
|
||||
}
|
||||
|
||||
function failureCountsLabel(entry: HistoryViewEntry): string {
|
||||
const values = [
|
||||
entry.downloadFailures,
|
||||
entry.offlineFailures,
|
||||
entry.extractionFailures,
|
||||
entry.remuxFailures,
|
||||
entry.cleanupFailures,
|
||||
entry.postProcessFailures
|
||||
];
|
||||
return values.every((value) => value === undefined)
|
||||
? "—"
|
||||
: values.map((value) => Math.max(0, Number(value) || 0)).join(" / ");
|
||||
}
|
||||
|
||||
export function paginateHistoryRows(rows: HistoryRow[], requestedPage: number): HistoryPage {
|
||||
const totalItems = rows.length;
|
||||
const totalPages = Math.max(1, Math.ceil(totalItems / HISTORY_PAGE_SIZE));
|
||||
@@ -209,7 +227,7 @@ function localDayStart(timestamp: number): number {
|
||||
}
|
||||
|
||||
function matchesTemporalFilter(entry: HistoryViewEntry, filter: HistoryFilter, now: number): boolean {
|
||||
if (filter === "completed" || filter === "deleted" || filter === "failed") {
|
||||
if (filter === "completed" || filter === "partial" || filter === "failed" || filter === "cancelled" || filter === "deleted") {
|
||||
return entry.status === filter;
|
||||
}
|
||||
if (filter === "all") {
|
||||
@@ -296,7 +314,8 @@ function toHistoryRow(entry: HistoryViewEntry): HistoryRow {
|
||||
remuxDurationLabel: formatHistoryDuration(entry.remuxDurationSeconds ?? 0),
|
||||
postProcessDurationLabel: formatHistoryDuration(entry.postProcessDurationSeconds ?? 0),
|
||||
totalDurationLabel: formatHistoryDuration(entry.totalDurationSeconds ?? 0),
|
||||
failurePhaseLabel: failurePhaseLabel(entry)
|
||||
failurePhaseLabel: failurePhaseLabel(entry),
|
||||
failureCountsLabel: failureCountsLabel(entry)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -332,6 +351,8 @@ function countHistoryFilters(entries: HistoryViewEntry[], now: number): HistoryF
|
||||
week: entries.filter((entry) => matchesTemporalFilter(entry, "week", now)).length,
|
||||
older: entries.filter((entry) => matchesTemporalFilter(entry, "older", now)).length,
|
||||
completed: entries.filter((entry) => entry.status === "completed").length,
|
||||
partial: entries.filter((entry) => entry.status === "partial").length,
|
||||
cancelled: entries.filter((entry) => entry.status === "cancelled").length,
|
||||
deleted: entries.filter((entry) => entry.status === "deleted").length,
|
||||
failed: entries.filter((entry) => entry.status === "failed").length
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user