aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm
diff options
context:
space:
mode:
authorstephan <stephan@noemail.net>2024-07-11 11:04:17 +0000
committerstephan <stephan@noemail.net>2024-07-11 11:04:17 +0000
commit9958c51a5d9b151aab4b5e6c1dd18188e94e99b6 (patch)
treec0b3670128254df5b2c3f58ca9adec130085d9c2 /ext/wasm
parent64ef4582c2018dac671282c3432c72a998549d24 (diff)
downloadsqlite-9958c51a5d9b151aab4b5e6c1dd18188e94e99b6.tar.gz
sqlite-9958c51a5d9b151aab4b5e6c1dd18188e94e99b6.zip
Add an option to force the opfs-sahpool VFS init to re-run after it fails on a first attempt, as a workaround for flaky environments where initial access to OPFS sync access handles is rejected but then permitted on a second attempt. Reported and discussed in [https://github.com/sqlite/sqlite-wasm/issues/79|issue #79 of the npm distribution].
FossilOrigin-Name: 5286e0f654d91a4ebee51fcabaab696e17ff07bb18990b401a31bd3d1213e695
Diffstat (limited to 'ext/wasm')
-rw-r--r--ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js45
-rw-r--r--ext/wasm/tester1.c-pp.js24
2 files changed, 50 insertions, 19 deletions
diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
index 3f4182dac..199ac7d61 100644
--- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
+++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
@@ -102,7 +102,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
clearOnInit: false,
/* Logging verbosity 3+ == everything, 2 == warnings+errors, 1 ==
errors only. */
- verbosity: 2
+ verbosity: 2,
+ forceReinitIfFailed: false
});
/** Logging routines, from most to least serious. */
@@ -1004,9 +1005,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return true;
};
- /** Only for testing a rejection case. */
- let instanceCounter = 0;
-
/**
installOpfsSAHPoolVfs() asynchronously initializes the OPFS
SyncAccessHandle (a.k.a. SAH) Pool VFS. It returns a Promise which
@@ -1081,12 +1079,26 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
the default directory. If no directory is explicitly provided
then a directory name is synthesized from the `name` option.
- Peculiarities of this VFS:
+
+ - `forceReinitIfFailed`: (default=`false`) Is a fallback option
+ to assist in working around certain flaky environments which may
+ mysteriously fail to permit access to OPFS sync access handles on
+ an initial attempt but permit it on a second attemp. This option
+ should never be used but is provided for those who choose to
+ throw caution to the wind and trust such environments. If this
+ option is truthy _and_ the previous attempt to initialize this
+ VFS with the same `name` failed, the VFS will attempt to
+ initialize a second time instead of returning the cached
+ failure. See discussion at:
+ <https://github.com/sqlite/sqlite-wasm/issues/79>
+
+
+ Peculiarities of this VFS vis a vis other SQLite VFSes:
- Paths given to it _must_ be absolute. Relative paths will not
be properly recognized. This is arguably a bug but correcting it
requires some hoop-jumping in routines which have no business
- doing tricks.
+ doing such tricks.
- It is possible to install multiple instances under different
names, each sandboxed from one another inside their own private
@@ -1207,13 +1219,19 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
handles are currently in use, e.g. by an sqlite3 db.
*/
sqlite3.installOpfsSAHPoolVfs = async function(options=Object.create(null)){
- const vfsName = options.name || optionDefaults.name;
- if(0 && 2===++instanceCounter){
- throw new Error("Just testing rejection.");
+ options = Object.assign(Object.create(null), optionDefaults, (options||{}));
+ const vfsName = options.name;
+ if(options.$testThrowPhase1){
+ throw options.$testThrowPhase1;
}
if(initPromises[vfsName]){
- //console.warn("Returning same OpfsSAHPool result",options,vfsName,initPromises[vfsName]);
- return initPromises[vfsName];
+ const p = initPromises[vfsName];
+ if( (p instanceof OpfsSAHPool) || !options.forceReinitIfFailed ){
+ //log("Returning cached installOpfsSAHPoolVfs() result",options,vfsName,initPromises[vfsName]);
+ return p;
+ }
+ delete initPromises[vfsName];
+ /* Fall through and try again. */
}
if(!globalThis.FileSystemHandle ||
!globalThis.FileSystemDirectoryHandle ||
@@ -1238,8 +1256,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
ensues.
*/
return initPromises[vfsName] = apiVersionCheck().then(async function(){
- if(options.$testThrowInInit){
- throw options.$testThrowInInit;
+ if(options.$testThrowPhase2){
+ throw options.$testThrowPhase2;
}
const thePool = new OpfsSAHPool(options);
return thePool.isReady.then(async()=>{
@@ -1255,7 +1273,6 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
oo1.DB.dbCtorHelper.call(this, opt);
};
OpfsSAHPoolDb.prototype = Object.create(oo1.DB.prototype);
- // yes or no? OpfsSAHPoolDb.PoolUtil = poolUtil;
poolUtil.OpfsSAHPoolDb = OpfsSAHPoolDb;
oo1.DB.dbCtorHelper.setVfsPostOpenSql(
theVfs.pointer,
diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js
index fe5bdc837..b1e05a24f 100644
--- a/ext/wasm/tester1.c-pp.js
+++ b/ext/wasm/tester1.c-pp.js
@@ -2824,7 +2824,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
name: 'Session API sanity checks',
predicate: ()=>!!capi.sqlite3changegroup_add,
test: function(sqlite3){
- warn("The session API tests could use some expansion.");
+ //warn("The session API tests could use some expansion.");
const db1 = new sqlite3.oo1.DB(), db2 = new sqlite3.oo1.DB();
const sqlInit = [
"create table t(rowid INTEGER PRIMARY KEY,a,b); ",
@@ -2859,7 +2859,9 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert('b4' === db1.selectValue('select b from t where rowid=4'))
.assert(3 === db1.selectValue('select count(*) from t'));
- const testSessionEnable = false;
+ const testSessionEnable =
+ false /* it's not yet clear whether these test failures are
+ broken tests or broken bindings. */;
if(testSessionEnable){
rc = capi.sqlite3session_enable(pSession, 0);
T.assert( 0 === rc )
@@ -2870,7 +2872,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert( capi.sqlite3session_enable(pSession, -1) > 0 )
.assert(undefined === db1.selectValue('select a from t where rowid=2'));
}else{
- warn("sqlite3session_enable() tests are currently disabled.");
+ //warn("sqlite3session_enable() tests are currently disabled.");
}
let db1Count = db1.selectValue("select count(*) from t");
T.assert( db1Count === (testSessionEnable ? 2 : 3) );
@@ -3177,13 +3179,25 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
.assert(!sqlite3.capi.sqlite3_vfs_find(sahPoolConfig.name));
let cErr, u3;
- conf2.$testThrowInInit = new Error("Testing throwing during init.");
+ conf2.$testThrowPhase2 = new Error("Testing throwing during init.");
conf2.name = sahPoolConfig.name+'-err';
const P3 = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e);
- T.assert(P3 === conf2.$testThrowInInit)
+ T.assert(P3 === conf2.$testThrowPhase2)
.assert(cErr === P3)
.assert(undefined === u3)
.assert(!sqlite3.capi.sqlite3_vfs_find(conf2.name));
+ delete conf2.$testThrowPhase2;
+ T.assert(cErr === await inst(conf2).catch(e=>e),
+ "Init result is cached even if it failed");
+
+ /* Ensure that the forceReinitIfFailed fallback bypasses the VFS init cache... */
+ cErr = u3 = undefined;
+ conf2.forceReinitIfFailed = true;
+ const P3b = await inst(conf2).then(u=>u3 = u).catch((e)=>cErr=e);
+ T.assert(undefined === cErr)
+ .assert(P3b === u3)
+ .assert(true === await u3.removeVfs())
+ .assert(false === await u3.removeVfs());
}
}/*OPFS SAH Pool sanity checks*/)