UNPKG

@speckle/objectloader2

Version:

This is an updated objectloader for the Speckle viewer written in typescript

93 lines 3.44 kB
import { isSafari } from '@speckle/shared'; import { Dexie } from 'dexie'; export class ObjectStore extends Dexie { static #databaseName = 'speckle-cache'; objects; // Table type: <entity, primaryKey> constructor(options) { super(ObjectStore.#databaseName, options); this.version(1).stores({ objects: 'baseId, item' // baseId is primary key }); } } export default class IndexedDatabase { #options; #logger; #cacheDB; #writeQueue; // #count: number = 0 constructor(options) { this.#options = options; this.#logger = options.logger || (() => { }); } async getAll(keys) { await this.#setupCacheDb(); let items = []; // this.#count++ // const startTime = performance.now() // this.#logger('Start read ' + x + ' ' + batch.length) //faster than BulkGet with dexie await this.#cacheDB.transaction('r', this.#cacheDB.objects, async () => { const gets = keys.map((key) => this.#cacheDB.objects.get(key)); const cachedData = await Promise.all(gets); items = cachedData; }); // const endTime = performance.now() // const duration = endTime - startTime //this.#logger('Saved batch ' + x + ' ' + batch.length + ' ' + duration / TIME_MS.second) return items; } async #openDatabase() { const db = new ObjectStore({ indexedDB: this.#options.indexedDB ?? globalThis.indexedDB, IDBKeyRange: this.#options.keyRange ?? IDBKeyRange, chromeTransactionDurability: 'relaxed' }); await db.open(); return db; } async #setupCacheDb() { if (this.#cacheDB !== undefined) { return; } // Initialize await this.#safariFix(); this.#cacheDB = await this.#openDatabase(); } async cacheSaveBatch(params) { await this.#setupCacheDb(); const { batch } = params; //const x = this.#count //this.#count++ // const startTime = performance.now() // this.#logger('Start save ' + x + ' ' + batch.length) await this.#cacheDB.objects.bulkPut(batch); // const endTime = performance.now() // const duration = endTime - startTime //this.#logger('Saved batch ' + x + ' ' + batch.length + ' ' + duration / TIME_MS.second) } /** * Fixes a Safari bug where IndexedDB requests get lost and never resolve - invoke before you use IndexedDB * @link Credits and more info: https://github.com/jakearchibald/safari-14-idb-fix */ async #safariFix() { // No point putting other browsers or older versions of Safari through this mess. if (!isSafari() || !this.#options.indexedDB?.databases) return Promise.resolve(); let intervalId; return new Promise((resolve) => { const tryIdb = () => this.#options.indexedDB?.databases().finally(resolve); intervalId = setInterval(() => { void tryIdb(); }, 100); void tryIdb(); }).finally(() => clearInterval(intervalId)); } async disposeAsync() { this.#cacheDB?.close(); this.#cacheDB = undefined; await this.#writeQueue?.disposeAsync(); this.#writeQueue = undefined; } } //# sourceMappingURL=indexedDatabase.js.map