feat(backend): Basic state save/restore

This commit is contained in:
Tibo De Peuter 2025-02-02 12:12:33 +01:00
parent 212c544eb1
commit 81b18df1f4
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2

View file

@ -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);