UNPKG

wowok

Version:

Wowok Blockchain TypeScript API

1 lines 4.35 kB
import{randomBytes}from'crypto';import{readFileSync,writeFileSync,renameSync,unlinkSync,existsSync,openSync,closeSync,constants}from'fs';export class PersistentStorage{['filePath'];['lock'];constructor(a){this['filePath']=a,this['lock']=new Lock(a+'.lock'),!existsSync(a)&&writeFileSync(a,JSON['stringify']({}));}async['readAll'](){await this['lock']['acquireShared']();try{const a=readFileSync(this['filePath'],'utf8');return JSON['parse'](a);}finally{await this['lock']['releaseShared']();}}async['writeAll'](a){await this['lock']['acquireExclusive']();try{const b=this['filePath']+'.tmp.'+randomBytes(0x8)['toString']('hex');writeFileSync(b,JSON['stringify'](a)),renameSync(b,this['filePath']);}finally{await this['lock']['releaseExclusive']();}}async['set'](a,b){await this['lock']['acquireExclusive']();try{const c=readFileSync(this['filePath'],'utf8'),d=JSON['parse'](c);d[a]=b;const e=this['filePath']+'.tmp.'+randomBytes(0x8)['toString']('hex');writeFileSync(e,JSON['stringify'](d)),renameSync(e,this['filePath']);}finally{await this['lock']['releaseExclusive']();}}async['get'](a){await this['lock']['acquireShared']();try{const b=readFileSync(this['filePath'],'utf8'),c=JSON['parse'](b);return c[a];}finally{await this['lock']['releaseShared']();}}async['transaction'](a){await this['lock']['acquireExclusive']();try{const b=readFileSync(this['filePath'],'utf8'),c=JSON['parse'](b),d=a(c),e=this['filePath']+'.tmp.'+randomBytes(0x8)['toString']('hex');writeFileSync(e,JSON['stringify'](d)),renameSync(e,this['filePath']);}finally{await this['lock']['releaseExclusive']();}}async['clear'](){await this['lock']['acquireExclusive']();try{const a=this['filePath']+'.tmp.'+randomBytes(0x8)['toString']('hex');writeFileSync(a,JSON['stringify']({})),renameSync(a,this['filePath']);}finally{await this['lock']['releaseExclusive']();}}}export class Lock{['lockPath'];['sharedLockPath'];['lockFd']=null;['sharedLockCount']=0x0;['exclusiveLockCount']=0x0;constructor(a){this['lockPath']=a,this['sharedLockPath']=a+'.shared';}async['acquireShared'](){if(this['exclusiveLockCount']>0x0){this['sharedLockCount']++,this['exclusiveLockCount']--;return;}if(this['sharedLockCount']>0x0){this['sharedLockCount']++;return;}let a=0x0;const b=0x64,c=0x32;while(a<b){try{if(existsSync(this['lockPath'])){await new Promise(d=>setTimeout(d,c)),a++;continue;}writeFileSync(this['sharedLockPath'],''),this['sharedLockCount']=0x1;return;}catch(d){await new Promise(e=>setTimeout(e,c)),a++;}}throw new Error('Failed\x20to\x20acquire\x20shared\x20lock\x20after\x20multiple\x20attempts');}async['acquireExclusive'](){if(this['exclusiveLockCount']>0x0){this['exclusiveLockCount']++;return;}let a=0x0;const b=0x64,c=0x32;while(a<b){try{if(existsSync(this['sharedLockPath'])){await new Promise(e=>setTimeout(e,c)),a++;continue;}const d=openSync(this['lockPath'],constants['O_CREAT']|constants['O_EXCL']|constants['O_WRONLY'],0x1a4);closeSync(d),this['exclusiveLockCount']=0x1;return;}catch(e){await new Promise(f=>setTimeout(f,c)),a++;}}throw new Error('Failed\x20to\x20acquire\x20exclusive\x20lock\x20after\x20multiple\x20attempts');}async['releaseShared'](){if(this['sharedLockCount']===0x0)throw new Error('No\x20shared\x20lock\x20to\x20release');this['sharedLockCount']--;if(this['sharedLockCount']===0x0)try{unlinkSync(this['sharedLockPath']);}catch(a){}}async['releaseExclusive'](){if(this['exclusiveLockCount']===0x0)throw new Error('No\x20exclusive\x20lock\x20to\x20release');this['exclusiveLockCount']--;if(this['exclusiveLockCount']===0x0)try{unlinkSync(this['lockPath']);}catch(a){}}}export class MultiProcessKVStore{['storage'];constructor(a){this['storage']=new PersistentStorage(a);}async['get'](a){return this['storage']['get'](a);}async['set'](a,b){return this['storage']['set'](a,b);}async['delete'](a){return this['storage']['transaction'](b=>{return delete b[a],b;});}async['has'](a){const b=await this['storage']['get'](a);return b!==undefined;}async['keys'](){const a=await this['storage']['readAll']();return Object['keys'](a);}async['values'](){const a=await this['storage']['readAll']();return Object['values'](a);}async['entries'](){const a=await this['storage']['readAll']();return Object['entries'](a);}async['clear'](){return this['storage']['clear']();}async['size'](){const a=await this['storage']['readAll']();return Object['keys'](a)['length'];}}