diff --git a/lib/background.ts b/lib/background.ts index ffe5f1e..7dadd65 100644 --- a/lib/background.ts +++ b/lib/background.ts @@ -27,6 +27,7 @@ import { } from "./browser"; import { Bus } from "./bus"; import { filterInSitu } from "./util"; +import { DB } from "./db"; const menus = typeof (_menus) !== "undefined" && _menus || _cmenus; @@ -662,6 +663,13 @@ locale.then(() => { await sessionRemover(); } + try { + await DB.init(); + } + catch (ex) { + console.error("dbinit", ex.toString(), ex.message, ex.stack, ex); + } + await Prefs.set("last-run", new Date()); await filters(); await getManager(); diff --git a/lib/db.ts b/lib/db.ts index 48db4ba..05e60f9 100644 --- a/lib/db.ts +++ b/lib/db.ts @@ -1,4 +1,5 @@ "use strict"; +// License: MIT // eslint-disable-next-line no-unused-vars import { BaseItem } from "./item"; @@ -6,12 +7,17 @@ import { BaseItem } from "./item"; import { Download } from "./manager/download"; import { RUNNING, QUEUED, RETRYING } from "./manager/state"; -// License: MIT - const VERSION = 1; const STORE = "queue"; -export const DB = new class DB { +interface Database { + init(): Promise; + saveItems(items: Download[]): Promise; + deleteItems(items: any[]): Promise; + getAll(): Promise; +} + +export class IDB implements Database { private db?: IDBDatabase; constructor() { @@ -106,7 +112,7 @@ export const DB = new class DB { return await new Promise(this.saveItemsInternal.bind(this, items)); } - deleteItemsInternal(items: any[], resolve: Function, reject: Function) { + deleteItemsInternal(items: any[], resolve: () => void, reject: Function) { if (!items || !items.length || !this.db) { resolve(); return; @@ -139,4 +145,70 @@ export const DB = new class DB { await this.init(); await new Promise(this.deleteItemsInternal.bind(this, items)); } +} + +class MemoryDB implements Database { + private counter = 1; + + private items = new Map(); + + init(): Promise { + return Promise.resolve(); + } + + saveItems(items: Download[]) { + for (const item of items) { + if (item.private) { + continue; + } + if (!item.dbId) { + item.dbId = ++this.counter; + } + this.items.set(item.dbId, item.toJSON()); + } + return Promise.resolve(); + } + + deleteItems(items: any[]) { + for (const item of items) { + if (!("dbId" in item)) { + continue; + } + this.items.delete(item.dbId); + } + return Promise.resolve(); + } + + getAll(): Promise { + return Promise.resolve(Array.from(this.items.values())); + } +} + +export const DB = new class DBWrapper implements Database { + saveItems(items: Download[]): Promise { + return this.db.saveItems(items); + } + + deleteItems(items: any[]): Promise { + return this.db.deleteItems(items); + } + + getAll(): Promise { + return this.db.getAll(); + } + + private db: Database; + + async init() { + try { + this.db = new IDB(); + await this.db.init(); + } + catch (ex) { + console.warn( + "Failed to initialize idb backend, using memory db fallback", ex); + this.db = new MemoryDB(); + await this.db.init(); + } + } }();