OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-unread-anchors / index.js

1 lines · javascript ref:
const t=require("hyperbee2"),e=require("ready-resource"),s=require("b4a"),i=require("compact-encoding"),{getEncoding:a}=require("./spec/hyperschema"),n=s.from([4]),o=a("@keet-unreads/unread-anchors"),r=a("@keet-unreads/info"),h=5e3,c=2,l=1;class u{constructor(t){this.unreads=t,this.ops=[]}tryPut(t,{timestamp:e=Date.now(),length:s=0}){this.ops.push({key:t,value:{timestamp:e,length:s}})}tryDelete(t){this.ops.push({key:t,value:null})}async flush(){if(!this.ops.length)return;await this.unreads.ready();const t=await this.unreads._getHead(),e=this.unreads.db.write({...t,type:1,timeout:h});for(const{key:t,value:a}of this.ops){const n=s.concat([s.from([1]),t]);a?e.tryPut(n,i.encode(o,a)):e.tryDelete(n)}e.tryPut(n,i.encode(r,{updated:Date.now()})),await e.flush()}}function d(){return null}module.exports=class extends e{constructor(e,s=[],i={}){super();const{encryptionKey:a,encryption:n=(a?{key:a}:null),name:o="local-unread",local:r=e.get({name:o,encryption:n}),blindPeering:h=null,target:c=null}=i;this.store=e,this.blindPeering=h,this.target=c,this.encryption=n,this.keys=s.slice(0),this.local=r,this.db=new t(this.store,{core:this.local,encryption:this.encryption,t:5}),this.views=[]}async addWriter(t){if(this.opened||await this.ready(),s.equals(t,this.local.key))return;for(const e of this.keys)if(s.equals(e,t))return;this.keys.push(t);const e=this.db.checkout({key:t,length:0});this.views.push(e),await this._initView(e)}async removeWriter(t){this.opened||await this.ready();for(let e=0;e<this.keys.length;e++){const i=this.keys[e],a=this.views[e];s.equals(i,t)&&(this.keys.splice(e,1),this.views.splice(e,1),await a.close())}}async _initView(t){await t.ready(),t.core.on("append",()=>{t.update(),this.emit("update"),t.core!==this.local&&this.emit("remote-update")}),t.update()}async _open(){await this.local.ready(),0===await this.db.compat()&&await this._reset(),this.views.push(this.db);const t=new Set([s.toString(this.db.core.key,"hex")]);for(const e of this.keys){const i=s.toString(e,"hex");t.has(i)||(t.add(i),this.views.push(this.db.checkout({key:e,length:0})))}for(const t of this.views)await this._initView(t);if(this.blindPeering){const t=await this.target;this.blindPeering.addCoreBackground(this.local,{target:t,pick:2})}}async _close(){for(let t=this.views.length-1;t>=0;t--)await this.views[t].close();await this.local.close(),await this.store.close()}write(){return new u(this)}async get(t){this.opened||await this.ready();const e=s.concat([s.from([1]),t]),a=new Array(this.views.length);for(let t=0;t<a.length;t++){const s=this.views[t];a[t]=s.get(e,{timeout:h}).catch(d)}const n=await Promise.all(a);let r=null;for(const t of n){if(!t)continue;const e=i.decode(o,t.value);(!r||r.timestamp<e.timestamp)&&(r=e)}return r}async reset(){this.opened||await this.ready(),await this._reset()}async _reset(){const t=this.db.write({key:this.local.key,length:0,type:1,timeout:h});t.tryPut(n,i.encode(r,{updated:Date.now()})),await t.flush()}async put(t,{timestamp:e=Date.now(),length:a=0}){this.opened||await this.ready();const c=await this._getHead(),l=await this.get(t);if(l&&l.length>=a)return;const u=this.db.write({...c,type:1,timeout:h}),d=s.concat([s.from([1]),t]);u.tryPut(d,i.encode(o,{timestamp:e,length:a})),u.tryPut(n,i.encode(r,{updated:Date.now()})),await u.flush()}async delete(t){this.opened||await this.ready();const e=await this._getHead();if(!await this.get(t))return;const a=this.db.write({...e,type:1,timeout:h}),o=s.concat([s.from([1]),t]);return a.tryDelete(o),a.tryPut(n,i.encode(r,{updated:Date.now()})),a.flush()}async _getHead(){const t=new Array(this.views.length);for(let e=0;e<t.length;e++){const s=this.views[e];t[e]=s.get(n,{timeout:h}).catch(d)}let e=null,s={key:this.local.key,length:0};const a=await Promise.all(t);for(const t of a){if(!t)continue;const a=i.decode(r,t.value);(!e||e.updated<a.updated)&&(e=a,s.key=t.core.key,s.length=t.core.length)}return s}};