From 81b18df1f497a092ecef25327b3d6c4ffbf6f569 Mon Sep 17 00:00:00 2001 From: Tibo De Peuter Date: Sun, 2 Feb 2025 12:12:33 +0100 Subject: [PATCH] feat(backend): Basic state save/restore --- backend/queueManager.ts | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/backend/queueManager.ts b/backend/queueManager.ts index aa4f11a..4c06ea0 100644 --- a/backend/queueManager.ts +++ b/backend/queueManager.ts @@ -1,10 +1,13 @@ import {fetchMetadata} from "./services/metadata"; import {DEFAULT_LUCIDA_OPTIONS, DownloadResult, LucidaOptions, ProcessingQueue, Queue, QueueItem} from "./types/queue"; import Lucida from "./services/lucida"; +import * as fs from "node:fs"; const TIMEOUT: number = 120000; const RETRIES: number = 5; +const STATE_FILE: string = '/data/state.json'; + class QueueManager { private readonly queue: Queue; private readonly processing: ProcessingQueue; @@ -20,6 +23,42 @@ class QueueManager { this.lucida = null; this.lucidaOptions = DEFAULT_LUCIDA_OPTIONS; + + this.loadState(); + } + + private saveState(): void { + const state = { + queue: this.processing.map(pi => pi.item).concat(this.queue), + history: this.history + }; + fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 4)); + } + + private loadState(): void { + if (!fs.existsSync(STATE_FILE)) { + return; + } + + const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')); + + console.log('QueueManager: Restoring state:', state); + + this.queue.push(...state.queue); + + state.history.forEach((item: QueueItem) => { + if (!this.queue.some(q => q.id === item.id)) { + if (item.result?.success) { + // Add successful items to the history + this.history.push(item); + } else { + // Add failed items to the queue + this.queue.push(item); + } + } + }); + + this.processQueue(); } public setLucidaOptions(options: LucidaOptions): void { @@ -58,6 +97,7 @@ class QueueManager { song: await fetchMetadata(song) }; this.queue.push(item); + this.saveState(); this.processQueue(); return item; @@ -74,6 +114,7 @@ class QueueManager { song: await fetchMetadata(song) }; this.queue.splice(index, 0, item); + this.saveState(); this.processQueue(); return item; @@ -87,11 +128,13 @@ class QueueManager { const item: QueueItem = this.queue[index]; this.queue.splice(index, 1); + this.saveState(); return item; } public clear(): void { this.queue.length = 0; + this.saveState(); } public move(song: string, to: number): QueueItem { @@ -102,6 +145,7 @@ class QueueManager { const item: QueueItem = this.queue.splice(index, 1)[0]; this.queue.splice(to, 0, item); + this.saveState(); return item; } @@ -114,6 +158,7 @@ class QueueManager { const item: QueueItem = this.history.splice(index, 1)[0]; item.retries = 0; this.queue.push(item); + this.saveState(); this.processQueue(); return item; @@ -149,9 +194,11 @@ class QueueManager { item.timeout = (item.timeout ?? TIMEOUT) * 2; item.result = result; this.queue.push(item); + this.saveState(); } else { item.result = result; this.history.push(item); + this.saveState(); } } catch (err) { item.result = { @@ -159,6 +206,7 @@ class QueueManager { error: err instanceof Error ? err.message : 'Unknown error' }; this.history.push(item); + this.saveState(); } this.processing.splice(this.processing.indexOf(current), 1);