feat(m4): persist the download queue across restarts
The queue/scheduler lived only in renderer memory, so saved/scheduled and other pending downloads were silently lost on quit (audit M4). Persist them: - main: queue.ts store (proven cached-atomic createJsonStore, queue.json) + queue:list / queue:save IPC; QUEUE_MAX cap. - shared: PersistedQueueItem = the durable subset of DownloadItem (runtime-only progress/speed/eta/sizeLabel/finishing dropped). - renderer: mirror the persistable items on every queue change (a signature over the subset means progress ticks don't re-save; main's jsonStore coalesces the writes) and rehydrate on launch via an App useEffect. Pure mappers extracted to store/queuePersist.ts and unit-tested. Restore semantics: downloading -> queued (yt-dlp continues the .part), saved + scheduledFor survives so the promoter fires when due, paused/error return actionable; completed/canceled are never persisted. A queueHydrated gate stops a launch-time store change from wiping queue.json before it's read. Reconciles ROADMAP.md. typecheck + 268 tests + eslint + prettier green. (OS-level quit/relaunch cycle is worth a manual smoke test.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,9 @@ export const IpcChannels = {
|
||||
ytdlpAutoUpdateStatus: 'ytdlp:auto-update-status',
|
||||
errorLogList: 'errorlog:list',
|
||||
errorLogClear: 'errorlog:clear',
|
||||
/** Persisted download queue (M4): saved/scheduled/pending items survive a quit. */
|
||||
queueList: 'queue:list',
|
||||
queueSave: 'queue:save',
|
||||
backupExport: 'backup:export',
|
||||
backupImport: 'backup:import',
|
||||
systemThemeGet: 'system-theme:get',
|
||||
@@ -501,6 +504,41 @@ export type DownloadEvent =
|
||||
| { type: 'done'; id: string; filePath?: string }
|
||||
| { type: 'error'; id: string; error: string }
|
||||
|
||||
/** The subset of a persisted queue item's status worth surviving a quit. */
|
||||
export type PersistedQueueStatus = 'queued' | 'downloading' | 'paused' | 'saved' | 'error'
|
||||
|
||||
/**
|
||||
* A queue item persisted across restarts (M4) so saved/scheduled and other pending
|
||||
* downloads return after a quit. This is the *durable* subset of the renderer's
|
||||
* `DownloadItem`: runtime-only fields (progress/speed/eta/sizeLabel/finishing) are
|
||||
* dropped since a restored item re-derives them. Transient results ('completed' /
|
||||
* 'canceled') are never persisted; on load a 'downloading' item is normalized back
|
||||
* to 'queued' because its process died with the previous session.
|
||||
*/
|
||||
export interface PersistedQueueItem {
|
||||
id: string
|
||||
url: string
|
||||
title: string
|
||||
channel?: string
|
||||
durationLabel?: string
|
||||
thumbnail?: string
|
||||
kind: MediaKind
|
||||
quality: string
|
||||
status: PersistedQueueStatus
|
||||
filePath?: string
|
||||
error?: string
|
||||
formatId?: string
|
||||
formatHasAudio?: boolean
|
||||
options?: DownloadOptions
|
||||
extraArgs?: string
|
||||
trim?: string
|
||||
scheduledFor?: number
|
||||
incognito?: boolean
|
||||
probedMeta?: DownloadMeta
|
||||
collection?: CollectionContext
|
||||
mediaItemId?: string
|
||||
}
|
||||
|
||||
/** Persisted user settings (electron-store). */
|
||||
export interface Settings {
|
||||
/** where video downloads are saved; empty string = the default Documents\Video folder */
|
||||
|
||||
Reference in New Issue
Block a user