aboutsummaryrefslogtreecommitdiff
path: root/ext/wasm/tests/opfs/concurrency/worker.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/wasm/tests/opfs/concurrency/worker.js')
-rw-r--r--ext/wasm/tests/opfs/concurrency/worker.js95
1 files changed, 95 insertions, 0 deletions
diff --git a/ext/wasm/tests/opfs/concurrency/worker.js b/ext/wasm/tests/opfs/concurrency/worker.js
new file mode 100644
index 000000000..7ba15bf8c
--- /dev/null
+++ b/ext/wasm/tests/opfs/concurrency/worker.js
@@ -0,0 +1,95 @@
+importScripts(
+ (new URL(self.location.href).searchParams).get('sqlite3.dir') + '/sqlite3.js'
+);
+self.sqlite3InitModule().then(async function(sqlite3){
+ const wName = Math.round(Math.random()*10000);
+ const wPost = (type,...payload)=>{
+ postMessage({type, worker: wName, payload});
+ };
+ const stdout = (...args)=>wPost('stdout',...args);
+ const stderr = (...args)=>wPost('stderr',...args);
+ const postErr = (...args)=>wPost('error',...args);
+ if(!sqlite3.opfs){
+ stderr("OPFS support not detected. Aborting.");
+ return;
+ }
+
+ const wait = async (ms)=>{
+ return new Promise((resolve)=>setTimeout(resolve,ms));
+ };
+
+ const dbName = 'concurrency-tester.db';
+ if((new URL(self.location.href).searchParams).has('unlink-db')){
+ await sqlite3.opfs.unlink(dbName);
+ stdout("Unlinked",dbName);
+ }
+ wPost('loaded');
+
+ const run = async function(){
+ const db = new sqlite3.opfs.OpfsDb(dbName);
+ //sqlite3.capi.sqlite3_busy_timeout(db.pointer, 2000);
+ db.transaction((db)=>{
+ db.exec([
+ "create table if not exists t1(w TEXT UNIQUE ON CONFLICT REPLACE,v);",
+ "create table if not exists t2(w TEXT UNIQUE ON CONFLICT REPLACE,v);"
+ ]);
+ });
+
+ const maxIterations = 10;
+ const interval = Object.assign(Object.create(null),{
+ delay: 300,
+ handle: undefined,
+ count: 0
+ });
+ stdout("Starting interval-based db updates with delay of",interval.delay,"ms.");
+ const doWork = async ()=>{
+ const tm = new Date().getTime();
+ ++interval.count;
+ const prefix = "v(#"+interval.count+")";
+ stdout("Setting",prefix,"=",tm);
+ try{
+ db.exec({
+ sql:"INSERT OR REPLACE INTO t1(w,v) VALUES(?,?)",
+ bind: [wName, new Date().getTime()]
+ });
+ //stdout("Set",prefix);
+ }catch(e){
+ interval.error = e;
+ }
+ };
+ const finish = ()=>{
+ if(interval.error) stderr("Ending work due to error:",e.message);
+ else stdout("Ending work after",interval.count,"interval(s)");
+ db.close();
+ };
+ if(1){/*use setInterval()*/
+ interval.handle = setInterval(async ()=>{
+ await doWork();
+ if(interval.error || maxIterations === interval.count){
+ clearInterval(interval.handle);
+ finish();
+ }
+ }, interval.delay);
+ }else{
+ /*This approach provides no concurrency whatsoever: each worker
+ is run to completion before any others can work.*/
+ let i;
+ for(i = 0; i < maxIterations; ++i){
+ await doWork();
+ if(interval.error) break;
+ await wait(interval.ms);
+ }
+ finish();
+ }
+ }/*run()*/;
+
+ self.onmessage = function({data}){
+ switch(data.type){
+ case 'run': run().catch((e)=>postErr(e.message));
+ break;
+ default:
+ stderr("Unhandled message type '"+data.type+"'.");
+ break;
+ }
+ };
+});