feat(notifications): alert on remaining volume
This commit is contained in:
@@ -62,6 +62,25 @@ export interface HistoryEntryContext {
|
||||
provider: DebridProvider | null;
|
||||
}
|
||||
|
||||
export interface RunRemainingSnapshot {
|
||||
remainingBytes: number;
|
||||
openItems: number;
|
||||
openPackages: number;
|
||||
unknownCount: number;
|
||||
speedBps: number;
|
||||
etaSeconds: number;
|
||||
}
|
||||
|
||||
export interface RemainingThresholdDecision {
|
||||
emit: boolean;
|
||||
remainingBytes?: number;
|
||||
}
|
||||
|
||||
export interface RemainingThresholdState {
|
||||
snapshot: RunRemainingSnapshot | null;
|
||||
crossings: number;
|
||||
}
|
||||
|
||||
const SUCCESS_TTL_MS = 6 * 60 * 60 * 1000;
|
||||
const IMPORTANT_TTL_MS = 24 * 60 * 60 * 1000;
|
||||
const DIGEST_PACKAGE_LIMIT = 20;
|
||||
@@ -73,6 +92,25 @@ function finiteNonNegative(value: unknown): number {
|
||||
return Number.isFinite(numeric) && numeric > 0 ? numeric : 0;
|
||||
}
|
||||
|
||||
export function evaluateRemainingThreshold(
|
||||
previous: RunRemainingSnapshot | null,
|
||||
current: RunRemainingSnapshot,
|
||||
thresholdBytes: number
|
||||
): RemainingThresholdDecision {
|
||||
const threshold = finiteNonNegative(thresholdBytes);
|
||||
if (!previous
|
||||
|| threshold <= 0
|
||||
|| previous.openItems <= 0
|
||||
|| current.openItems <= 0
|
||||
|| previous.unknownCount > 0
|
||||
|| current.unknownCount > 0
|
||||
|| previous.remainingBytes <= threshold
|
||||
|| current.remainingBytes > threshold) {
|
||||
return { emit: false };
|
||||
}
|
||||
return { emit: true, remainingBytes: current.remainingBytes };
|
||||
}
|
||||
|
||||
function formatBytes(bytes: number): string {
|
||||
let value = finiteNonNegative(bytes);
|
||||
const units = ["B", "KB", "MB", "GB", "TB", "PB"];
|
||||
@@ -285,6 +323,31 @@ export function buildRunNotificationEvent(result: RunResult): NotificationEvent
|
||||
);
|
||||
}
|
||||
|
||||
export function buildRemainingThresholdNotificationEvent(
|
||||
runId: string,
|
||||
crossing: number,
|
||||
snapshot: RunRemainingSnapshot,
|
||||
thresholdBytes: number,
|
||||
createdAt: number
|
||||
): NotificationEvent {
|
||||
return event(
|
||||
`run:${runId}:remaining_threshold_crossed:${crossing}`,
|
||||
"remaining_threshold_crossed",
|
||||
"success",
|
||||
createdAt,
|
||||
"📉 Restmenge erreicht",
|
||||
`Der aktive Durchlauf liegt bei oder unter ${formatBytes(thresholdBytes)}.`,
|
||||
0x3498db,
|
||||
[
|
||||
{ name: "Restmenge", value: formatBytes(snapshot.remainingBytes), inline: true },
|
||||
{ name: "Offene Pakete", value: String(snapshot.openPackages), inline: true },
|
||||
{ name: "Offene Dateien", value: String(snapshot.openItems), inline: true },
|
||||
{ name: "Geschwindigkeit", value: snapshot.speedBps > 0 ? `${formatBytes(snapshot.speedBps)}/s` : "—", inline: true },
|
||||
{ name: "ETA", value: snapshot.etaSeconds >= 0 ? formatDuration(snapshot.etaSeconds) : "—", inline: true }
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function buildHistoryEntry(
|
||||
result: PackageResult,
|
||||
context: HistoryEntryContext
|
||||
|
||||
Reference in New Issue
Block a user