@speckle/objectloader2
Version:
This is an updated objectloader for the Speckle viewer written in typescript
93 lines • 3.44 kB
JavaScript
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