@@ -4,6 +4,7 @@ import { WebLocksExclusive as WebLocks } from './WebLocks.js';
44import { IDBContext } from './IDBContext.js' ;
55
66const SECTOR_SIZE = 512 ;
7+ const MAX_TASK_MILLIS = 3000 ;
78
89/**
910 * @typedef VFSOptions
@@ -53,6 +54,9 @@ export class IDBBatchAtomicVFS extends VFS.Base {
5354 /** @type {IDBContext } */ #idb;
5455 /** @type {Set<string> } */ #pendingPurges = new Set ( ) ;
5556
57+ #taskTimestamp = performance . now ( ) ;
58+ #pendingAsync = new Set ( ) ;
59+
5660 constructor ( idbDatabaseName = 'wa-sqlite' , options = DEFAULT_OPTIONS ) {
5761 super ( ) ;
5862 this . name = idbDatabaseName ;
@@ -67,7 +71,7 @@ export class IDBBatchAtomicVFS extends VFS.Base {
6771 await this . xClose ( fileId ) ;
6872 }
6973
70- this . #idb?. close ( ) ;
74+ await this . #idb?. close ( ) ;
7175 this . #idb = null ;
7276 }
7377
@@ -203,6 +207,36 @@ export class IDBBatchAtomicVFS extends VFS.Base {
203207 * @returns {number }
204208 */
205209 xWrite ( fileId , pData , iOffset ) {
210+ // Handle asynchronously every MAX_TASK_MILLIS milliseconds. This is
211+ // tricky because Asyncify calls asynchronous methods twice: once
212+ // to initiate the call and unwinds the stack, then rewinds the
213+ // stack and calls again to retrieve the completed result.
214+ const rewound = this . #pendingAsync. has ( fileId ) ;
215+ if ( rewound || performance . now ( ) - this . #taskTimestamp > MAX_TASK_MILLIS ) {
216+ const result = this . handleAsync ( async ( ) => {
217+ if ( this . handleAsync !== super . handleAsync ) {
218+ this . #pendingAsync. add ( fileId ) ;
219+ }
220+ await new Promise ( resolve => setTimeout ( resolve ) ) ;
221+
222+ const result = this . #xWriteHelper( fileId , pData , iOffset ) ;
223+ this . #taskTimestamp = performance . now ( ) ;
224+ return result ;
225+ } ) ;
226+
227+ if ( rewound ) this . #pendingAsync. delete ( fileId ) ;
228+ return result ;
229+ }
230+ return this . #xWriteHelper( fileId , pData , iOffset ) ;
231+ }
232+
233+ /**
234+ * @param {number } fileId
235+ * @param {Uint8Array } pData
236+ * @param {number } iOffset
237+ * @returns {number }
238+ */
239+ #xWriteHelper( fileId , pData , iOffset ) {
206240 const file = this . #mapIdToFile. get ( fileId ) ;
207241 log ( `xWrite ${ file . path } ${ pData . byteLength } ${ iOffset } ` ) ;
208242
@@ -275,25 +309,49 @@ export class IDBBatchAtomicVFS extends VFS.Base {
275309
276310 /**
277311 * @param {number } fileId
278- * @param {* } flags
312+ * @param {number } flags
279313 * @returns {number }
280314 */
281315 xSync ( fileId , flags ) {
316+ // Skip IndexedDB sync if durability is relaxed and the last
317+ // sync was recent enough.
318+ const rewound = this . #pendingAsync. has ( fileId ) ;
319+ if ( rewound || this . #options. durability !== 'relaxed' ||
320+ performance . now ( ) - this . #taskTimestamp > MAX_TASK_MILLIS ) {
321+ const result = this . handleAsync ( async ( ) => {
322+ if ( this . handleAsync !== super . handleAsync ) {
323+ this . #pendingAsync. add ( fileId ) ;
324+ }
325+
326+ const result = await this . #xSyncHelper( fileId , flags ) ;
327+ this . #taskTimestamp = performance . now ( ) ;
328+ return result ;
329+ } ) ;
330+
331+ if ( rewound ) this . #pendingAsync. delete ( fileId ) ;
332+ return result ;
333+ }
334+
282335 const file = this . #mapIdToFile. get ( fileId ) ;
283336 log ( `xSync ${ file . path } ${ flags } ` ) ;
337+ return VFS . SQLITE_OK ;
338+ }
284339
340+ /**
341+ * @param {number } fileId
342+ * @param {number } flags
343+ * @returns {Promise<number> }
344+ */
345+ async #xSyncHelper( fileId , flags ) {
346+ const file = this . #mapIdToFile. get ( fileId ) ;
347+ log ( `xSync ${ file . path } ${ flags } ` ) ;
285348 try {
286- if ( this . #options. durability !== 'relaxed' ) {
287- return this . handleAsync ( async ( ) => {
288- await this . #idb. sync ( ) ;
289- return VFS . SQLITE_OK ;
290- } ) ;
291- }
292- return VFS . SQLITE_OK ;
349+ await this . #idb. sync ( ) ;
293350 } catch ( e ) {
294351 console . error ( e ) ;
295352 return VFS . SQLITE_IOERR ;
296353 }
354+ return VFS . SQLITE_OK ;
297355 }
298356
299357 /**
0 commit comments