Skip to content

add shareWorker/Worker #583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

add shareWorker/Worker #583

wants to merge 1 commit into from

Conversation

nenge123
Copy link

function getWorker(port,data,tables){return new Promise(back=>{port.addEventListener('message',async function(e){console.log(this);if(e.data=='complete'||e.data&&e.data.result=='complete'){let sql=new(class{constructor(port){console.log(port);this.port=port;this.port.addEventListener('message',x=>{let xx=x.data;if(xx&&xx.constructor===Object){let id=xx.id;if(this.feedback[id]instanceof Function){return this.feedback[id](xx)}console.log(xx)}})}feedback={};getRandom(){return crypto?crypto.randomUUID():btoa(performance.now()+Math.random())}async getMessage(result,method){return await this.getResult({result,method})}async getResult(result,transf){return new Promise((back,error)=>{const id=this.getRandom();this.feedback[id]=function(data){const id=data.id;if(id&&this[id]instanceof Function){delete this[id]}if(data.error)return error(data.error);back(data.result)};result.id=id;this.postMessage(result,transf)})}postMessage(result,transf){this.port.postMessage(result,transf)}})(this);let method=await sql.getResult({result:[data,tables],method:'install'},data instanceof Uint8Array?[data.buffer]:[]);method.forEach(v=>{if(v=='constructor')return;sql[v]=new Function('...result','return this.getResult({result,method:"'+v+'"})')});back(sql)}},{once:true})})}

let share = new SharedWorker('worker2.js','SQLite');
//let share = new SharedWorker('worker2.js?idb','SQLite');
//idb will use indexedb save/load sql-wasm.js/sql-wasm.wasm
//let worker = new Worker('worker2.js');
//let worker = new Worker('worker2.js?idb');
//let sqlite = await getWorker(worker);
share.port.start();
let sqlite = await getWorker(share.port,uint8,{...tables});//tables: {data:{id:'int int primary key',value:'char'}};
await sqlite.insert('data',{id:1,value:'are you ok?'});
await sqlite.all('select * from `data`');
await sqlite.all('select * from `data` where `id` = ?',[1]);
await sqlite.once('select * from `data` where `id` = ?',[1]);
await sqlite.result('select `value` from `data` where `id` = ?',[1]); //are you ok?

```javascript
function getWorker(port,data,tables){return new Promise(back=>{port.addEventListener('message',async function(e){console.log(this);if(e.data=='complete'||e.data&&e.data.result=='complete'){let sql=new(class{constructor(port){console.log(port);this.port=port;this.port.addEventListener('message',x=>{let xx=x.data;if(xx&&xx.constructor===Object){let id=xx.id;if(this.feedback[id]instanceof Function){return this.feedback[id](xx)}console.log(xx)}})}feedback={};getRandom(){return crypto?crypto.randomUUID():btoa(performance.now()+Math.random())}async getMessage(result,method){return await this.getResult({result,method})}async getResult(result,transf){return new Promise((back,error)=>{const id=this.getRandom();this.feedback[id]=function(data){const id=data.id;if(id&&this[id]instanceof Function){delete this[id]}if(data.error)return error(data.error);back(data.result)};result.id=id;this.postMessage(result,transf)})}postMessage(result,transf){this.port.postMessage(result,transf)}})(this);let method=await sql.getResult({result:[data,tables],method:'install'},data instanceof Uint8Array?[data.buffer]:[]);method.forEach(v=>{if(v=='constructor')return;sql[v]=new Function('...result','return this.getResult({result,method:"'+v+'"})')});back(sql)}},{once:true})})}

let share = new SharedWorker('worker2.js','SQLite');
//let share = new SharedWorker('worker2.js?idb','SQLite');
//idb will use indexedb save/load sql-wasm.js/sql-wasm.wasm
//let worker = new Worker('worker2.js');
//let worker = new Worker('worker2.js?idb');
//let sqlite = await getWorker(worker);
share.port.start();
let sqlite = await getWorker(share.port,uint8,{...tables});//tables: {data:{id:'int int primary key',value:'char'}};
await sqlite.insert('data',{id:1,value:'are you ok?'});
await sqlite.all('select * from `data`');
await sqlite.all('select * from `data` where `id` = ?',[1]);
await sqlite.once('select * from `data` where `id` = ?',[1]);
await sqlite.result('select `value` from `data` where `id` = ?',[1]); //are you ok?

```
@nenge123
Copy link
Author

//old code method
await sqlite.postMessage({
    id:1,
    action:"exec",
    sql: "SELECT * FROM test",
    config: {useBigInt: true}, /*Optional param*/
  });

@@ -0,0 +1 @@
new class{ports=[];constructor(name,table){const S=this;self.S=S;const isLocal=/(127\.0\.0\.1|localhost|local\.nenge\.net)/.test(location.host)||/(cdn|npm)/.test(location.host);const mode=self.location.search.indexOf('idb')!==-1;const root=self.location.href.split('/').slice(0,-1).join('/')+'/';this.name=name||'sql-lite';this.table=table||'files';this.datafile='data.sqlite3';this.jsfile=isLocal?root+'sql-wasm.js':'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js';this.wasmfile=isLocal?root+'sql-wasm.wasm':'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.wasm';this.ready=new Promise(async(ok,error)=>{try{await(mode?this.loadDB():this.loadImport())}catch(e){error(e);throw e;}if(self.postMessage){self.addEventListener('message',this.baseMessage);self.postMessage({result:'complete',database:self.database instanceof self.SQLite})}ok(true)});self.addEventListener("rejectionhandled",(event)=>{console.log(`Promise rejected;reason:${event.reason}`)});self.addEventListener("unhandledrejection",(event)=>{console.log(`Promise unhandled rejected;reason:${event.reason}`)});if(self.SharedWorkerGlobalScope&&self instanceof self.SharedWorkerGlobalScope){self.onconnect=async function(e){const source=e.source;await self.S.ready;source.onmessage=self.S.baseMessage;source.postMessage({result:'complete',database:self.database instanceof self.SQLite})}}}async loadImport(){importScripts(this.jsfile);this.onRuntimeInitialized(await initSqlJs());return true}postError(e){postMessage({method:'error',error:e});throw e;}async loadDB(){let script=await this.getItem('sql-wasm.js');if(!script){let response=await fetch(this.jsfile).catch(e=>this.postError(e));if(response&&response.status==200){script=await response.blob();this.setItem('sql-wasm.js',script)}else{throw'file error';}}let initSqlJs=(new Function(await script.text()+';return initSqlJs;'))();let wasmBinary=await this.getItem('sql-wasm.wasm');if(!wasmBinary){let response=await fetch(this.wasmfile).catch(e=>this.postError(e));if(response&&response.status==200){wasmBinary=new Uint8Array(await response.arrayBuffer());this.setItem('sql-wasm.wasm',wasmBinary)}else{throw'file error';}}this.onRuntimeInitialized(await initSqlJs({wasmBinary}));return true}methods={async install(data){if(data.result[0]===true){self.database=new self.SQLite(await self.S.getData(),data.result[1])}else{self.database=new self.SQLite(...data.result)}return this.getMethod()},async reload(data){if(self.database)self.database.close();if(!(data.result instanceof Array))data.result=[data.result];this.install(data);return true},getMethod(){return['run','exec','close','each'].concat(Reflect.ownKeys(self.SQLite.prototype))},closeworker(data,port){port.postMessage({id:data.id,result:true});self.close();throw'close';},async save2exit(data,port){port.postMessage({id:data.id,result:true});await self.database.savedata();self.close();throw'close';},old_create(){if(!self.database)self.database=new self.SQLite()},old_nosql(data,port){if(!data.sql){port.postMessage({id:data.id,error:"exec: Missing query string"});return true}return false},old_open(data,port){if(self.database)self.database.close();self.database=new self.SQLite(Uint8Array(data['buffer']));port.postMessage({id:data.id,ready:true})},old_exec(data,port){this.old_create();if(this.old_nosql(data,port))return;port.postMessage({id:data.id,results:db.exec(data.sql,data["params"],data.config)})},old_each(data,port){this.old_create();if(this.old_nosql(data,port))return;self.database.each(data.sql,data.param,row=>{port.postMessage({id:data.id,row:row,finished:false})},()=>port.postMessage({id:data.id,finished:true}),data.config)},old_export(data,port){this.old_create();const result={id:data.id,buffer:self.database.export()};port.postMessage(result,[result.buffer.buffer])},old_close(){if(self.database)self.database.close();port.postMessage({id:data.id})}};onRuntimeInitialized(SQL){const S=this;delete SQL.wasmBinary;self.SQLite=class extends SQL.Database{constructor(data,tablelist){super(data instanceof Uint8Array?data:undefined);if(tablelist&&!(data instanceof Uint8Array)){this.createtable(tablelist)}}all(sql,params,limit){let result=this.exec(sql,params);if(result[0]){let data=[];for(let value of result[0].values){data.push(Object.fromEntries(value.map((v,k)=>[result[0].columns[k],v])));if(limit)break}return data}}one(sql,params){let result=this.all(sql,params,1);if(result&&result[0]){return result[0]}}columns(index,sql,params){let result=Object.values(this.one(sql,params)||[]);if(result.length){return result[index||0]}}result(sql,params){return this.columns(0,sql,params)}delete(table,where){let whereStr=Array.from(Object.keys(where),e=>'`'+e+'` = ? ').join(' AND ');this.run('DELETE FROM `'+table+'` WHERE '+whereStr+';',Object.values(where))}insert(table,data,where){if(where){this.delete(table,where)}return this.result('INSERT INTO `'+table+'` ('+Array.from(Object.keys(data),e=>'`'+e+'`').join(',')+') VALUES ('+Object.keys(data).fill('?').join(',')+');',Object.values(data))}update(table,data,where){let setStr=Array.from(Object.keys(data),e=>'`'+e+'` = ?').join(',');let whereStr=Array.from(Object.keys(where),e=>'`'+e+'` = ? ').join(' AND ');let param=Object.values(data);param.push(...Object.values(where));return this.run('UPDATE `'+table+'` SET '+setStr+' WHERE '+whereStr+' ;',param)}createtable(tablelist){Array.from(Object.entries(tablelist)||[],entry=>{let keys=Array.from(Object.entries(entry[1]),sub=>{return'`'+sub[0]+'` '+sub[1]}).join(',');this.run(`CREATE TABLE\`${entry[0]}\`(${keys});`)})}async savedata(){return await S.setItem(self.S.datafile,this.export())}}}async open(version){if(this.idb instanceof Promise)return await this.idb;if(!this.idb){this.idb=new Promise(resolve=>{let req=indexedDB.open(this.name,version);req.addEventListener("upgradeneeded",e=>{const db=req.result;if(!db.objectStoreNames.contains(this.table)){const store=db.createObjectStore(this.table);store.createIndex('timestamp','timestamp',{"unique":false})}},{once:true});req.addEventListener('success',async e=>{const db=req.result;if(!db.objectStoreNames.contains(this.table)){let version=db.version+=1;db.close();return resolve(await this.open(version))}return resolve(db)},{once:true})})}return this.idb}async ObjectStore(ReadMode){const db=await this.open();const transaction=db.transaction([this.table],ReadMode?undefined:"readwrite");return transaction.objectStore(this.table)}readOnly(){return this.ObjectStore(!0)}readWrite(){return this.ObjectStore()}async getItem(name){let request=(await this.readOnly()).get(name);return new Promise((resolve)=>request.addEventListener('success',(e)=>{resolve(e.target.result&&e.target.result.contents||e.target.result)}))}async setItem(name,contents){let request=(await this.readWrite()).put({contents,timestamp:new Date},name);return new Promise((resolve)=>request.addEventListener('success',(e)=>{resolve(e.target.result)}))}async getData(){return await this.getItem(this.datafile)}async baseMessage(e){const data=e.data;if(data&&data.constructor===Object){const id=data.id;if(data.action){data.config=data.config?data.config:{};if(self.S.methods['old_'+data.action]instanceof Function)return self.S.methods['old_'+data.action](data,this);return this.postMessage({id:data.id,error:"Invalid action : "+data["action"]})}const method=data.method;const transf=[];let newResult={id};if(self.database&&self.database[method]instanceof Function){if(!(data.result instanceof Array))data.result=data.result?[data.result]:[];try{newResult.result=self.database[method](...data.result)}catch(e){newResult.error=e}}else if(self.S.methods[method]instanceof Function){newResult.result=await self.S.methods[method](data,this);if(!newResult.result)return}else{newResult.error='undefined:method or database or not create'}if(newResult.error)delete newResult.result;if(newResult.result instanceof Uint8Array)transf.push(newResult.result.buffer);this.postMessage(newResult,transf)}}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, you can't add this kind of obfuscated undocumented code to the repo

@lovasoa lovasoa closed this Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants