ziron-rendezvous
Version:
1 lines • 2.07 kB
JavaScript
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const crypto=require("crypto"),Utils_1=require("./Utils");class RendezvousMapper{constructor(t={}){if(this._clusterCount=0,this._clusters=[],this._virtualLevelCount=0,null!=t.fanout&&t.fanout>9)throw new Error("The fanout option cannot be higher than 9");this._fanout=t.fanout||2,this._hashAlgorithm=t.hashAlgorithm||"md5",this._targetClusterSize=t.targetClusterSize||16,this._minClusterSize=t.minClusterSize||this._targetClusterSize}static _logx(t,e){return Math.log(t)/Math.log(e)}static _getVirtualLevelCount(t,e){return Math.ceil(RendezvousMapper._logx(t,e))}_hash(t){return crypto.createHash(this._hashAlgorithm).update(t).digest("hex")}_generateClusters(t){(t=t.filter(Utils_1.distinctArrayFilter)).sort(),this._clusters=[],this._clusterCount=Math.ceil(t.length/this._targetClusterSize);for(let t=0;t<this._clusterCount;t++)this._clusters[t]=[];let e=0;for(let s=0;s<t.length;s++){let i=this._clusters[e];i.push(t[s]),i.length>=this._targetClusterSize&&e++}if(this._clusterCount>1){const t=this._clusters[this._clusterCount-1];if(t.length<this._minClusterSize){this._clusters.pop(),this._clusterCount--,e=0;for(let s=0;s<t.length;s++){this._clusters[e].push(t[s]),e=(e+1)%this._clusterCount}}}this._virtualLevelCount=RendezvousMapper._getVirtualLevelCount(this._clusterCount,this._fanout)}setSites(t){this._generateClusters(t)}getSites(){const t=[];for(let e=0;e<this._clusterCount;e++)t.push(...this._clusters[e]);return t}findSite(t,e=0){const s=e.toString();let i="";for(let e=0;e<this._virtualLevelCount;e++){let r=null,l=0;for(let i=0;i<this._fanout;i++){const u=this._hash(t+s+e+i);(!r||u>r)&&(r=u,l=i)}i+=l.toString()}let r=parseInt(i,this._fanout)||0,l=this._clusters[r];if(null==l)return 0===r?null:this.findSite(t,e+1);const u=l[this._findIndexWithHighestRandomWeight(t+e+i,l)];return null==u?this.findSite(t,e+1):u}_findIndexWithHighestRandomWeight(t,e){let s=0,i=null;for(let r=0;r<e.length;r++){const l=this._hash(t+e[r]);(!i||l>i)&&(i=l,s=r)}return s}}exports.default=RendezvousMapper;