diff --git a/packages/common/nbstore/src/impls/idb/blob.ts b/packages/common/nbstore/src/impls/idb/blob.ts index d06292951d..9abb02c773 100644 --- a/packages/common/nbstore/src/impls/idb/blob.ts +++ b/packages/common/nbstore/src/impls/idb/blob.ts @@ -1,5 +1,9 @@ import { share } from '../../connection'; -import { type BlobRecord, BlobStorageBase } from '../../storage'; +import { + type BlobRecord, + BlobStorageBase, + type ListedBlobRecord, +} from '../../storage'; import { IDBConnection, type IDBConnectionOptions } from './db'; export class IndexedDBBlobStorage extends BlobStorageBase { @@ -32,9 +36,7 @@ export class IndexedDBBlobStorage extends BlobStorageBase { } override async set(blob: BlobRecord) { - const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite'); await trx.objectStore('blobs').put({ key: blob.key, mime: blob.mime, @@ -50,15 +52,11 @@ export class IndexedDBBlobStorage extends BlobStorageBase { override async delete(key: string, permanently: boolean) { if (permanently) { - const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite'); await trx.objectStore('blobs').delete(key); await trx.objectStore('blobData').delete(key); } else { - const trx = this.db.transaction('blobs', 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction('blobs', 'readwrite'); const blob = await trx.store.get(key); if (blob) { await trx.store.put({ @@ -70,37 +68,29 @@ export class IndexedDBBlobStorage extends BlobStorageBase { } override async release() { - const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction(['blobs', 'blobData'], 'readwrite'); - const store = trx.objectStore('blobs'); - const getAllRecords = store.getAllRecords?.bind(store); - const blobs = - typeof getAllRecords === 'function' - ? (await getAllRecords()).map(record => record.value) - : await store.getAll(); + const it = trx.objectStore('blobs').iterate(); - const deleted = blobs.filter(blob => blob.deletedAt); - - await Promise.all( - deleted.map(blob => - Promise.all([ - store.delete(blob.key), - trx.objectStore('blobData').delete(blob.key), - ]) - ) - ); + for await (const item of it) { + if (item.value.deletedAt) { + await item.delete(); + await trx.objectStore('blobData').delete(item.value.key); + } + } } override async list() { const trx = this.db.transaction('blobs', 'readonly'); - const getAllRecords = trx.store.getAllRecords?.bind(trx.store); - const blobs = - typeof getAllRecords === 'function' - ? (await getAllRecords()).map(record => record.value) - : await trx.store.getAll(); + const it = trx.store.iterate(); - return blobs.filter(blob => !blob.deletedAt); + const blobs: ListedBlobRecord[] = []; + for await (const item of it) { + if (!item.value.deletedAt) { + blobs.push(item.value); + } + } + + return blobs; } } diff --git a/packages/common/nbstore/src/impls/idb/db.ts b/packages/common/nbstore/src/impls/idb/db.ts index 1e29f49d64..0326ab91e2 100644 --- a/packages/common/nbstore/src/impls/idb/db.ts +++ b/packages/common/nbstore/src/impls/idb/db.ts @@ -4,38 +4,6 @@ import { AutoReconnectConnection } from '../../connection'; import type { SpaceType } from '../../utils/universal-id'; import { type DocStorageSchema, migrator } from './schema'; -declare module 'idb' { - interface IDBPObjectStore { - getAllRecords?( - query?: IDBValidKey | IDBKeyRange | null, - count?: number | { direction?: IDBCursorDirection; count?: number } - ): Promise; - } - interface IDBPIndex { - getAllRecords?( - query?: IDBValidKey | IDBKeyRange | null, - count?: number | { direction?: IDBCursorDirection; count?: number } - ): Promise; - } - interface IDBObjectStore { - getAllRecords?( - query?: IDBValidKey | IDBKeyRange | null, - count?: number | { direction?: IDBCursorDirection; count?: number } - ): Promise; - } - interface IDBIndex { - getAllRecords?( - query?: IDBValidKey | IDBKeyRange | null, - count?: number | { direction?: IDBCursorDirection; count?: number } - ): Promise; - } - interface IDBRecord { - key: IDBValidKey; - primaryKey: IDBValidKey; - value: any; - } -} - export interface IDBConnectionOptions { flavour: string; type: SpaceType; diff --git a/packages/common/nbstore/src/impls/idb/doc.ts b/packages/common/nbstore/src/impls/idb/doc.ts index c6977f6baa..46ca0bc4bc 100644 --- a/packages/common/nbstore/src/impls/idb/doc.ts +++ b/packages/common/nbstore/src/impls/idb/doc.ts @@ -37,9 +37,7 @@ export class IndexedDBDocStorage extends DocStorageBase { while (true) { try { - const trx = this.db.transaction(['updates', 'clocks'], 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction(['updates', 'clocks'], 'readwrite'); await trx.objectStore('updates').add({ ...update, @@ -105,15 +103,15 @@ export class IndexedDBDocStorage extends DocStorageBase { override async deleteDoc(docId: string) { const trx = this.db.transaction( ['snapshots', 'updates', 'clocks'], - 'readwrite', - { durability: 'relaxed' } + 'readwrite' ); - const updates = trx.objectStore('updates'); - const idx = updates.index('docId'); - const keys = await idx.getAllKeys(IDBKeyRange.only(docId)); + const idx = trx.objectStore('updates').index('docId'); + const iter = idx.iterate(IDBKeyRange.only(docId)); - await Promise.all(keys.map(key => updates.delete(key))); + for await (const { value } of iter) { + await trx.objectStore('updates').delete([value.docId, value.createdAt]); + } await trx.objectStore('snapshots').delete(docId); await trx.objectStore('clocks').delete(docId); @@ -122,18 +120,6 @@ export class IndexedDBDocStorage extends DocStorageBase { override async getDocTimestamps(after: Date = new Date(0)) { const trx = this.db.transaction('clocks', 'readonly'); - const getAllRecords = trx.store.getAllRecords?.bind(trx.store); - - if (typeof getAllRecords === 'function') { - const records = await getAllRecords(); - return records.reduce((ret, cur) => { - if (cur.value.timestamp > after) { - ret[cur.value.docId] = cur.value.timestamp; - } - return ret; - }, {} as DocClocks); - } - const clocks = await trx.store.getAll(); return clocks.reduce((ret, cur) => { @@ -171,19 +157,7 @@ export class IndexedDBDocStorage extends DocStorageBase { protected override async getDocUpdates(docId: string): Promise { const trx = this.db.transaction('updates', 'readonly'); - const idx = trx.store.index('docId'); - const getAllRecords = idx.getAllRecords?.bind(idx); - - if (typeof getAllRecords === 'function') { - const records = await getAllRecords(IDBKeyRange.only(docId)); - return records.map(record => ({ - docId, - bin: record.value.bin, - timestamp: record.value.createdAt, - })); - } - - const updates = await idx.getAll(docId); + const updates = await trx.store.index('docId').getAll(docId); return updates.map(update => ({ docId, @@ -196,9 +170,7 @@ export class IndexedDBDocStorage extends DocStorageBase { docId: string, updates: DocRecord[] ): Promise { - const trx = this.db.transaction('updates', 'readwrite', { - durability: 'relaxed', - }); + const trx = this.db.transaction('updates', 'readwrite'); await Promise.all( updates.map(update => trx.store.delete([docId, update.timestamp]))