diff --git a/dist/es5node/leader-election.js b/dist/es5node/leader-election.js index 38448aaa..5c3a9715 100644 --- a/dist/es5node/leader-election.js +++ b/dist/es5node/leader-election.js @@ -33,8 +33,6 @@ var LeaderElection = function LeaderElection(broadcastChannel, options) { this._lstns = []; // _listeners - this._invs = []; // _intervals - this._dpL = function () {}; // onduplicate listener @@ -69,7 +67,8 @@ LeaderElection.prototype = { * false if not. * @async */ - applyOnce: function applyOnce() { + applyOnce: function applyOnce( // true if the applyOnce() call came from the fallbackInterval cycle + isFromFallbackInterval) { var _this2 = this; if (this.isLeader) { @@ -144,10 +143,23 @@ LeaderElection.prototype = { }; _this2.broadcastChannel.addEventListener('internal', handleMessage); + /** + * If the applyOnce() call came from the fallbackInterval, + * we can assume that the election runs in the background and + * not critical process is waiting for it. + * When this is true, we give the other intances + * more time to answer to messages in the election cycle. + * This makes it less likely to elect duplicate leaders. + * But also it takes longer which is not a problem because we anyway + * run in the background. + */ + + + var waitForAnswerTime = isFromFallbackInterval ? _this2._options.responseTime * 4 : _this2._options.responseTime; var applyPromise = _sendMessage(_this2, 'apply') // send out that this one is applying .then(function () { - return Promise.race([(0, _util.sleep)(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([(0, _util.sleep)(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); }) // send again in case another instance was just created @@ -155,7 +167,7 @@ LeaderElection.prototype = { return _sendMessage(_this2, 'apply'); }) // let others time to respond .then(function () { - return Promise.race([(0, _util.sleep)(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([(0, _util.sleep)(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); })["catch"](function () {}).then(function () { @@ -208,12 +220,6 @@ LeaderElection.prototype = { this._lstns = []; - this._invs.forEach(function (interval) { - return clearInterval(interval); - }); - - this._invs = []; - this._unl.forEach(function (uFn) { return uFn.remove(); }); @@ -247,7 +253,6 @@ function _awaitLeadershipOnce(leaderElector) { } resolved = true; - clearInterval(interval); leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -257,18 +262,33 @@ function _awaitLeadershipOnce(leaderElector) { if (leaderElector.isLeader) { finish(); } - }); // try on fallbackInterval + }); + /** + * Try on fallbackInterval + * @recursive + */ + + var tryOnFallBack = function tryOnFallBack() { + return (0, _util.sleep)(leaderElector._options.fallbackInterval).then(function () { + if (leaderElector.isDead || resolved) { + return; + } - var interval = setInterval(function () { - leaderElector.applyOnce().then(function () { if (leaderElector.isLeader) { finish(); + } else { + return leaderElector.applyOnce(true).then(function () { + if (leaderElector.isLeader) { + finish(); + } else { + tryOnFallBack(); + } + }); } }); - }, leaderElector._options.fallbackInterval); - - leaderElector._invs.push(interval); // try when other leader dies + }; + tryOnFallBack(); // try when other leader dies var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { diff --git a/dist/esbrowser/leader-election.js b/dist/esbrowser/leader-election.js index 1cba9ff2..c8c9cbb4 100644 --- a/dist/esbrowser/leader-election.js +++ b/dist/esbrowser/leader-election.js @@ -24,8 +24,6 @@ var LeaderElection = function LeaderElection(broadcastChannel, options) { this._lstns = []; // _listeners - this._invs = []; // _intervals - this._dpL = function () {}; // onduplicate listener @@ -60,7 +58,8 @@ LeaderElection.prototype = { * false if not. * @async */ - applyOnce: function applyOnce() { + applyOnce: function applyOnce( // true if the applyOnce() call came from the fallbackInterval cycle + isFromFallbackInterval) { var _this2 = this; if (this.isLeader) { @@ -135,10 +134,23 @@ LeaderElection.prototype = { }; _this2.broadcastChannel.addEventListener('internal', handleMessage); + /** + * If the applyOnce() call came from the fallbackInterval, + * we can assume that the election runs in the background and + * not critical process is waiting for it. + * When this is true, we give the other intances + * more time to answer to messages in the election cycle. + * This makes it less likely to elect duplicate leaders. + * But also it takes longer which is not a problem because we anyway + * run in the background. + */ + + + var waitForAnswerTime = isFromFallbackInterval ? _this2._options.responseTime * 4 : _this2._options.responseTime; var applyPromise = _sendMessage(_this2, 'apply') // send out that this one is applying .then(function () { - return Promise.race([sleep(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([sleep(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); }) // send again in case another instance was just created @@ -146,7 +158,7 @@ LeaderElection.prototype = { return _sendMessage(_this2, 'apply'); }) // let others time to respond .then(function () { - return Promise.race([sleep(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([sleep(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); })["catch"](function () {}).then(function () { @@ -199,12 +211,6 @@ LeaderElection.prototype = { this._lstns = []; - this._invs.forEach(function (interval) { - return clearInterval(interval); - }); - - this._invs = []; - this._unl.forEach(function (uFn) { return uFn.remove(); }); @@ -238,7 +244,6 @@ function _awaitLeadershipOnce(leaderElector) { } resolved = true; - clearInterval(interval); leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -248,18 +253,33 @@ function _awaitLeadershipOnce(leaderElector) { if (leaderElector.isLeader) { finish(); } - }); // try on fallbackInterval + }); + /** + * Try on fallbackInterval + * @recursive + */ + + var tryOnFallBack = function tryOnFallBack() { + return sleep(leaderElector._options.fallbackInterval).then(function () { + if (leaderElector.isDead || resolved) { + return; + } - var interval = setInterval(function () { - leaderElector.applyOnce().then(function () { if (leaderElector.isLeader) { finish(); + } else { + return leaderElector.applyOnce(true).then(function () { + if (leaderElector.isLeader) { + finish(); + } else { + tryOnFallBack(); + } + }); } }); - }, leaderElector._options.fallbackInterval); - - leaderElector._invs.push(interval); // try when other leader dies + }; + tryOnFallBack(); // try when other leader dies var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { diff --git a/dist/esnode/leader-election.js b/dist/esnode/leader-election.js index 1cba9ff2..c8c9cbb4 100644 --- a/dist/esnode/leader-election.js +++ b/dist/esnode/leader-election.js @@ -24,8 +24,6 @@ var LeaderElection = function LeaderElection(broadcastChannel, options) { this._lstns = []; // _listeners - this._invs = []; // _intervals - this._dpL = function () {}; // onduplicate listener @@ -60,7 +58,8 @@ LeaderElection.prototype = { * false if not. * @async */ - applyOnce: function applyOnce() { + applyOnce: function applyOnce( // true if the applyOnce() call came from the fallbackInterval cycle + isFromFallbackInterval) { var _this2 = this; if (this.isLeader) { @@ -135,10 +134,23 @@ LeaderElection.prototype = { }; _this2.broadcastChannel.addEventListener('internal', handleMessage); + /** + * If the applyOnce() call came from the fallbackInterval, + * we can assume that the election runs in the background and + * not critical process is waiting for it. + * When this is true, we give the other intances + * more time to answer to messages in the election cycle. + * This makes it less likely to elect duplicate leaders. + * But also it takes longer which is not a problem because we anyway + * run in the background. + */ + + + var waitForAnswerTime = isFromFallbackInterval ? _this2._options.responseTime * 4 : _this2._options.responseTime; var applyPromise = _sendMessage(_this2, 'apply') // send out that this one is applying .then(function () { - return Promise.race([sleep(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([sleep(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); }) // send again in case another instance was just created @@ -146,7 +158,7 @@ LeaderElection.prototype = { return _sendMessage(_this2, 'apply'); }) // let others time to respond .then(function () { - return Promise.race([sleep(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([sleep(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); })["catch"](function () {}).then(function () { @@ -199,12 +211,6 @@ LeaderElection.prototype = { this._lstns = []; - this._invs.forEach(function (interval) { - return clearInterval(interval); - }); - - this._invs = []; - this._unl.forEach(function (uFn) { return uFn.remove(); }); @@ -238,7 +244,6 @@ function _awaitLeadershipOnce(leaderElector) { } resolved = true; - clearInterval(interval); leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -248,18 +253,33 @@ function _awaitLeadershipOnce(leaderElector) { if (leaderElector.isLeader) { finish(); } - }); // try on fallbackInterval + }); + /** + * Try on fallbackInterval + * @recursive + */ + + var tryOnFallBack = function tryOnFallBack() { + return sleep(leaderElector._options.fallbackInterval).then(function () { + if (leaderElector.isDead || resolved) { + return; + } - var interval = setInterval(function () { - leaderElector.applyOnce().then(function () { if (leaderElector.isLeader) { finish(); + } else { + return leaderElector.applyOnce(true).then(function () { + if (leaderElector.isLeader) { + finish(); + } else { + tryOnFallBack(); + } + }); } }); - }, leaderElector._options.fallbackInterval); - - leaderElector._invs.push(interval); // try when other leader dies + }; + tryOnFallBack(); // try when other leader dies var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { diff --git a/dist/lib/browser.js b/dist/lib/browser.js index e4f400ad..f2586943 100644 --- a/dist/lib/browser.js +++ b/dist/lib/browser.js @@ -401,8 +401,6 @@ var LeaderElection = function LeaderElection(broadcastChannel, options) { this._lstns = []; // _listeners - this._invs = []; // _intervals - this._dpL = function () {}; // onduplicate listener @@ -437,7 +435,8 @@ LeaderElection.prototype = { * false if not. * @async */ - applyOnce: function applyOnce() { + applyOnce: function applyOnce( // true if the applyOnce() call came from the fallbackInterval cycle + isFromFallbackInterval) { var _this2 = this; if (this.isLeader) { @@ -512,10 +511,23 @@ LeaderElection.prototype = { }; _this2.broadcastChannel.addEventListener('internal', handleMessage); + /** + * If the applyOnce() call came from the fallbackInterval, + * we can assume that the election runs in the background and + * not critical process is waiting for it. + * When this is true, we give the other intances + * more time to answer to messages in the election cycle. + * This makes it less likely to elect duplicate leaders. + * But also it takes longer which is not a problem because we anyway + * run in the background. + */ + + + var waitForAnswerTime = isFromFallbackInterval ? _this2._options.responseTime * 4 : _this2._options.responseTime; var applyPromise = _sendMessage(_this2, 'apply') // send out that this one is applying .then(function () { - return Promise.race([(0, _util.sleep)(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([(0, _util.sleep)(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); }) // send again in case another instance was just created @@ -523,7 +535,7 @@ LeaderElection.prototype = { return _sendMessage(_this2, 'apply'); }) // let others time to respond .then(function () { - return Promise.race([(0, _util.sleep)(_this2._options.responseTime / 2), stopCriteriaPromise.then(function () { + return Promise.race([(0, _util.sleep)(waitForAnswerTime), stopCriteriaPromise.then(function () { return Promise.reject(new Error()); })]); })["catch"](function () {}).then(function () { @@ -576,12 +588,6 @@ LeaderElection.prototype = { this._lstns = []; - this._invs.forEach(function (interval) { - return clearInterval(interval); - }); - - this._invs = []; - this._unl.forEach(function (uFn) { return uFn.remove(); }); @@ -615,7 +621,6 @@ function _awaitLeadershipOnce(leaderElector) { } resolved = true; - clearInterval(interval); leaderElector.broadcastChannel.removeEventListener('internal', whenDeathListener); res(true); } // try once now @@ -625,18 +630,33 @@ function _awaitLeadershipOnce(leaderElector) { if (leaderElector.isLeader) { finish(); } - }); // try on fallbackInterval + }); + /** + * Try on fallbackInterval + * @recursive + */ + + var tryOnFallBack = function tryOnFallBack() { + return (0, _util.sleep)(leaderElector._options.fallbackInterval).then(function () { + if (leaderElector.isDead || resolved) { + return; + } - var interval = setInterval(function () { - leaderElector.applyOnce().then(function () { if (leaderElector.isLeader) { finish(); + } else { + return leaderElector.applyOnce(true).then(function () { + if (leaderElector.isLeader) { + finish(); + } else { + tryOnFallBack(); + } + }); } }); - }, leaderElector._options.fallbackInterval); - - leaderElector._invs.push(interval); // try when other leader dies + }; + tryOnFallBack(); // try when other leader dies var whenDeathListener = function whenDeathListener(msg) { if (msg.context === 'leader' && msg.action === 'death') { diff --git a/dist/lib/browser.min.js b/dist/lib/browser.min.js index 2ec55e94..4f9e70dd 100644 --- a/dist/lib/browser.min.js +++ b/dist/lib/browser.min.js @@ -1 +1 @@ -!function r(o,i,s){function a(t,e){if(!i[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(u)return u(t,!0);throw(n=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",n}n=i[t]={exports:{}},o[t][0].call(n.exports,function(e){return a(o[t][1][e]||e)},n,n.exports,r,o,i,s)}return i[t].exports}for(var u="function"==typeof require&&require,e=0;e=e.time&&e.fn(t.data)})},n=e.method.microSeconds(),e._prepP?e._prepP.then(function(){e._iL=!0,e.method.onMessage(e._state,t,n)}):(e._iL=!0,e.method.onMessage(e._state,t,n)))}}(e)}function h(e,t,n){e._addEL[t]=e._addEL[t].filter(function(e){return e!==n}),function(e){{var t;e._iL&&!d(e)&&(e._iL=!1,t=e.method.microSeconds(),e.method.onMessage(e._state,null,t))}}(e)}(n.BroadcastChannel=a)._pubkey=!0,a.prototype={postMessage:function(e){if(this.closed)throw new Error("BroadcastChannel.postMessage(): Cannot post message after channel has closed");return l(this,"message",e)},postInternal:function(e){return l(this,"internal",e)},set onmessage(e){var t={time:this.method.microSeconds(),fn:e};h(this,"message",this._onML),e&&"function"==typeof e?(this._onML=t,f(this,"message",t)):this._onML=null},addEventListener:function(e,t){var n=this.method.microSeconds();f(this,e,{time:n,fn:t})},removeEventListener:function(e,t){var n=this._addEL[e].find(function(e){return e.fn===t});h(this,e,n)},close:function(){var e=this;if(!this.closed){s.delete(this),this.closed=!0;var t=this._prepP||o.PROMISE_RESOLVED_VOID;return this._onML=null,this._addEL.message=[],t.then(function(){return Promise.all(Array.from(e._uMP))}).then(function(){return Promise.all(e._befC.map(function(e){return e()}))}).then(function(){return e.method.close(e._state)})}},get type(){return this.method.type},get isClosed(){return this.closed}}},{"./method-chooser.js":6,"./options.js":11,"./util.js":12}],2:[function(e,t,n){"use strict";var r=e("./index.es5.js"),e=r.BroadcastChannel,r=r.createLeaderElection;window.BroadcastChannel2=e,window.createLeaderElection=r},{"./index.es5.js":3}],3:[function(e,t,n){"use strict";e=e("./index.js");t.exports={BroadcastChannel:e.BroadcastChannel,createLeaderElection:e.createLeaderElection,clearNodeFolder:e.clearNodeFolder,enforceOptions:e.enforceOptions,beLeader:e.beLeader}},{"./index.js":4}],4:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"BroadcastChannel",{enumerable:!0,get:function(){return r.BroadcastChannel}}),Object.defineProperty(n,"OPEN_BROADCAST_CHANNELS",{enumerable:!0,get:function(){return r.OPEN_BROADCAST_CHANNELS}}),Object.defineProperty(n,"beLeader",{enumerable:!0,get:function(){return o.beLeader}}),Object.defineProperty(n,"clearNodeFolder",{enumerable:!0,get:function(){return r.clearNodeFolder}}),Object.defineProperty(n,"createLeaderElection",{enumerable:!0,get:function(){return o.createLeaderElection}}),Object.defineProperty(n,"enforceOptions",{enumerable:!0,get:function(){return r.enforceOptions}});var r=e("./broadcast-channel"),o=e("./leader-election")},{"./broadcast-channel":1,"./leader-election":5}],5:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.beLeader=u,n.createLeaderElection=function(e,t){if(e._leaderElector)throw new Error("BroadcastChannel already has a leader-elector");t=function(e,t){e=e||{};(e=JSON.parse(JSON.stringify(e))).fallbackInterval||(e.fallbackInterval=3e3);e.responseTime||(e.responseTime=t.method.averageResponseTime(t.options));return e}(t,e);var n=new o(e,t);return e._befC.push(function(){return n.die()}),e._leaderElector=n};var s=e("./util.js"),r=e("unload"),o=function(e,t){var n=this;this.broadcastChannel=e,this._options=t,this.isLeader=!1,this.hasLeader=!1,this.isDead=!1,this.token=(0,s.randomToken)(),this._aplQ=s.PROMISE_RESOLVED_VOID,this._aplQC=0,this._unl=[],this._lstns=[],this._invs=[],this._dpL=function(){},this._dpLC=!1;function r(e){"leader"===e.context&&("death"===e.action&&(n.hasLeader=!1),"tell"===e.action&&(n.hasLeader=!0))}this.broadcastChannel.addEventListener("internal",r),this._lstns.push(r)};function a(e,t){t={context:"leader",action:t,token:e.token};return e.broadcastChannel.postInternal(t)}function u(t){t.isLeader=!0,t.hasLeader=!0;var e=(0,r.add)(function(){return t.die()});t._unl.push(e);function n(e){"leader"===e.context&&"apply"===e.action&&a(t,"tell"),"leader"!==e.context||"tell"!==e.action||t._dpLC||(t._dpLC=!0,t._dpL(),a(t,"tell"))}return t.broadcastChannel.addEventListener("internal",n),t._lstns.push(n),a(t,"tell")}o.prototype={applyOnce:function(){var i=this;if(this.isLeader)return(0,s.sleep)(0,!0);if(this.isDead)return(0,s.sleep)(0,!1);if(1i.token&&t(),"tell"===e.action&&(t(),i.hasLeader=!0))}var t,n=!1,r=new Promise(function(e){t=function(){n=!0,e()}}),o=[];return i.broadcastChannel.addEventListener("internal",e),a(i,"apply").then(function(){return Promise.race([(0,s.sleep)(i._options.responseTime/2),r.then(function(){return Promise.reject(new Error)})])}).then(function(){return a(i,"apply")}).then(function(){return Promise.race([(0,s.sleep)(i._options.responseTime/2),r.then(function(){return Promise.reject(new Error)})])}).catch(function(){}).then(function(){return i.broadcastChannel.removeEventListener("internal",e),!n&&u(i).then(function(){return!0})})}return this._aplQC=this._aplQC+1,this._aplQ=this._aplQ.then(e).then(function(){i._aplQC=i._aplQC-1}),this._aplQ.then(function(){return i.isLeader})},awaitLeadership:function(){return this._aLP||(this._aLP=function(i){if(i.isLeader)return s.PROMISE_RESOLVED_VOID;return new Promise(function(e){var t=!1;function n(){t||(t=!0,clearInterval(r),i.broadcastChannel.removeEventListener("internal",o),e(!0))}i.applyOnce().then(function(){i.isLeader&&n()});var r=setInterval(function(){i.applyOnce().then(function(){i.isLeader&&n()})},i._options.fallbackInterval);i._invs.push(r);var o=function(e){"leader"===e.context&&"death"===e.action&&(i.hasLeader=!1,i.applyOnce().then(function(){i.isLeader&&n()}))};i.broadcastChannel.addEventListener("internal",o),i._lstns.push(o)})}(this)),this._aLP},set onduplicate(e){this._dpL=e},die:function(){var t=this;return this._lstns.forEach(function(e){return t.broadcastChannel.removeEventListener("internal",e)}),this._lstns=[],this._invs.forEach(function(e){return clearInterval(e)}),this._invs=[],this._unl.forEach(function(e){return e.remove()}),this._unl=[],this.isLeader&&(this.hasLeader=!1,this.isLeader=!1),this.isDead=!0,a(this,"death")}}},{"./util.js":12,unload:20}],6:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");e("@babel/runtime/helpers/typeof");Object.defineProperty(n,"__esModule",{value:!0}),n.chooseMethod=function(t){var e=[].concat(t.methods,u).filter(Boolean);if(t.type){if("simulate"===t.type)return s.default;var n=e.find(function(e){return e.type===t.type});if(n)return n;throw new Error("method-type "+t.type+" not found")}t.webWorkerSupport||a.isNode||(e=e.filter(function(e){return"idb"!==e.type}));e=e.find(function(e){return e.canBeUsed()});{if(e)return e;throw new Error("No useable method found in "+JSON.stringify(u.map(function(e){return e.type})))}};var o=r(e("./methods/native.js")),i=r(e("./methods/indexed-db.js")),n=r(e("./methods/localstorage.js")),s=r(e("./methods/simulate.js")),a=e("./util");var u=[o.default,i.default,n.default]},{"./methods/indexed-db.js":7,"./methods/localstorage.js":8,"./methods/native.js":9,"./methods/simulate.js":10,"./util":12,"@babel/runtime/helpers/interopRequireDefault":13,"@babel/runtime/helpers/typeof":14}],7:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.averageResponseTime=y,n.canBeUsed=w,n.cleanOldMessages=p,n.close=b,n.create=m,n.createDatabase=c,n.default=void 0,n.getAllMessages=function(e){var n=e.transaction(a).objectStore(a),r=[];return new Promise(function(t){n.openCursor().onsuccess=function(e){e=e.target.result;e?(r.push(e.value),e.continue()):t(r)}})},n.getIdb=u,n.getMessagesHigherThan=d,n.getOldMessages=h,n.microSeconds=void 0,n.onMessage=g,n.postMessage=_,n.removeMessageById=f,n.type=void 0,n.writeMessage=l;var o=e("../util.js"),i=e("oblivious-set"),s=e("../options"),e=o.microSeconds;n.microSeconds=e;var r="pubkey.broadcast-channel-0-",a="messages";function u(){if("undefined"!=typeof indexedDB)return indexedDB;if("undefined"!=typeof window){if(void 0!==window.mozIndexedDB)return window.mozIndexedDB;if(void 0!==window.webkitIndexedDB)return window.webkitIndexedDB;if(void 0!==window.msIndexedDB)return window.msIndexedDB}return!1}function c(e){var n=u().open(r+e,1);return n.onupgradeneeded=function(e){e.target.result.createObjectStore(a,{keyPath:"id",autoIncrement:!0})},new Promise(function(e,t){n.onerror=function(e){return t(e)},n.onsuccess=function(){e(n.result)}})}function l(e,t,n){var r={uuid:t,time:(new Date).getTime(),data:n},o=e.transaction([a],"readwrite");return new Promise(function(e,t){o.oncomplete=function(){return e()},o.onerror=function(e){return t(e)},o.objectStore(a).add(r)})}function d(e,n){var r=e.transaction(a).objectStore(a),o=[];return new Promise(function(t){(function(){try{var e=IDBKeyRange.bound(n+1,1/0);return r.openCursor(e)}catch(e){return r.openCursor()}})().onsuccess=function(e){e=e.target.result;e?e.value.idn.lastCursorId&&(n.lastCursorId=e.id),e}).filter(function(e){return t=n,(e=e).uuid!==t.uuid&&(!t.eMIs.has(e.id)&&!(e.data.time=e.time&&e.fn(t.data)})},n=e.method.microSeconds(),e._prepP?e._prepP.then(function(){e._iL=!0,e.method.onMessage(e._state,t,n)}):(e._iL=!0,e.method.onMessage(e._state,t,n)))}}(e)}function h(e,t,n){e._addEL[t]=e._addEL[t].filter(function(e){return e!==n}),function(e){{var t;e._iL&&!d(e)&&(e._iL=!1,t=e.method.microSeconds(),e.method.onMessage(e._state,null,t))}}(e)}(n.BroadcastChannel=a)._pubkey=!0,a.prototype={postMessage:function(e){if(this.closed)throw new Error("BroadcastChannel.postMessage(): Cannot post message after channel has closed");return l(this,"message",e)},postInternal:function(e){return l(this,"internal",e)},set onmessage(e){var t={time:this.method.microSeconds(),fn:e};h(this,"message",this._onML),e&&"function"==typeof e?(this._onML=t,f(this,"message",t)):this._onML=null},addEventListener:function(e,t){var n=this.method.microSeconds();f(this,e,{time:n,fn:t})},removeEventListener:function(e,t){var n=this._addEL[e].find(function(e){return e.fn===t});h(this,e,n)},close:function(){var e=this;if(!this.closed){s.delete(this),this.closed=!0;var t=this._prepP||o.PROMISE_RESOLVED_VOID;return this._onML=null,this._addEL.message=[],t.then(function(){return Promise.all(Array.from(e._uMP))}).then(function(){return Promise.all(e._befC.map(function(e){return e()}))}).then(function(){return e.method.close(e._state)})}},get type(){return this.method.type},get isClosed(){return this.closed}}},{"./method-chooser.js":6,"./options.js":11,"./util.js":12}],2:[function(e,t,n){"use strict";var r=e("./index.es5.js"),e=r.BroadcastChannel,r=r.createLeaderElection;window.BroadcastChannel2=e,window.createLeaderElection=r},{"./index.es5.js":3}],3:[function(e,t,n){"use strict";e=e("./index.js");t.exports={BroadcastChannel:e.BroadcastChannel,createLeaderElection:e.createLeaderElection,clearNodeFolder:e.clearNodeFolder,enforceOptions:e.enforceOptions,beLeader:e.beLeader}},{"./index.js":4}],4:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"BroadcastChannel",{enumerable:!0,get:function(){return r.BroadcastChannel}}),Object.defineProperty(n,"OPEN_BROADCAST_CHANNELS",{enumerable:!0,get:function(){return r.OPEN_BROADCAST_CHANNELS}}),Object.defineProperty(n,"beLeader",{enumerable:!0,get:function(){return o.beLeader}}),Object.defineProperty(n,"clearNodeFolder",{enumerable:!0,get:function(){return r.clearNodeFolder}}),Object.defineProperty(n,"createLeaderElection",{enumerable:!0,get:function(){return o.createLeaderElection}}),Object.defineProperty(n,"enforceOptions",{enumerable:!0,get:function(){return r.enforceOptions}});var r=e("./broadcast-channel"),o=e("./leader-election")},{"./broadcast-channel":1,"./leader-election":5}],5:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.beLeader=l,n.createLeaderElection=function(e,t){if(e._leaderElector)throw new Error("BroadcastChannel already has a leader-elector");t=function(e,t){e=e||{};(e=JSON.parse(JSON.stringify(e))).fallbackInterval||(e.fallbackInterval=3e3);e.responseTime||(e.responseTime=t.method.averageResponseTime(t.options));return e}(t,e);var n=new o(e,t);return e._befC.push(function(){return n.die()}),e._leaderElector=n};var u=e("./util.js"),r=e("unload"),o=function(e,t){var n=this;this.broadcastChannel=e,this._options=t,this.isLeader=!1,this.hasLeader=!1,this.isDead=!1,this.token=(0,u.randomToken)(),this._aplQ=u.PROMISE_RESOLVED_VOID,this._aplQC=0,this._unl=[],this._lstns=[],this._dpL=function(){},this._dpLC=!1;function r(e){"leader"===e.context&&("death"===e.action&&(n.hasLeader=!1),"tell"===e.action&&(n.hasLeader=!0))}this.broadcastChannel.addEventListener("internal",r),this._lstns.push(r)};function c(e,t){t={context:"leader",action:t,token:e.token};return e.broadcastChannel.postInternal(t)}function l(t){t.isLeader=!0,t.hasLeader=!0;var e=(0,r.add)(function(){return t.die()});t._unl.push(e);function n(e){"leader"===e.context&&"apply"===e.action&&c(t,"tell"),"leader"!==e.context||"tell"!==e.action||t._dpLC||(t._dpLC=!0,t._dpL(),c(t,"tell"))}return t.broadcastChannel.addEventListener("internal",n),t._lstns.push(n),c(t,"tell")}o.prototype={applyOnce:function(s){var a=this;if(this.isLeader)return(0,u.sleep)(0,!0);if(this.isDead)return(0,u.sleep)(0,!1);if(1a.token&&t(),"tell"===e.action&&(t(),a.hasLeader=!0))}var t,n=!1,r=new Promise(function(e){t=function(){n=!0,e()}}),o=[];a.broadcastChannel.addEventListener("internal",e);var i=s?4*a._options.responseTime:a._options.responseTime;return c(a,"apply").then(function(){return Promise.race([(0,u.sleep)(i),r.then(function(){return Promise.reject(new Error)})])}).then(function(){return c(a,"apply")}).then(function(){return Promise.race([(0,u.sleep)(i),r.then(function(){return Promise.reject(new Error)})])}).catch(function(){}).then(function(){return a.broadcastChannel.removeEventListener("internal",e),!n&&l(a).then(function(){return!0})})}return this._aplQC=this._aplQC+1,this._aplQ=this._aplQ.then(e).then(function(){a._aplQC=a._aplQC-1}),this._aplQ.then(function(){return a.isLeader})},awaitLeadership:function(){return this._aLP||(this._aLP=function(o){if(o.isLeader)return u.PROMISE_RESOLVED_VOID;return new Promise(function(e){var t=!1;function n(){t||(t=!0,o.broadcastChannel.removeEventListener("internal",r),e(!0))}o.applyOnce().then(function(){o.isLeader&&n()}),function e(){return(0,u.sleep)(o._options.fallbackInterval).then(function(){if(!o.isDead&&!t)return o.isLeader?void n():o.applyOnce(!0).then(function(){(o.isLeader?n:e)()})})}();var r=function(e){"leader"===e.context&&"death"===e.action&&(o.hasLeader=!1,o.applyOnce().then(function(){o.isLeader&&n()}))};o.broadcastChannel.addEventListener("internal",r),o._lstns.push(r)})}(this)),this._aLP},set onduplicate(e){this._dpL=e},die:function(){var t=this;return this._lstns.forEach(function(e){return t.broadcastChannel.removeEventListener("internal",e)}),this._lstns=[],this._unl.forEach(function(e){return e.remove()}),this._unl=[],this.isLeader&&(this.hasLeader=!1,this.isLeader=!1),this.isDead=!0,c(this,"death")}}},{"./util.js":12,unload:20}],6:[function(e,t,n){"use strict";var r=e("@babel/runtime/helpers/interopRequireDefault");e("@babel/runtime/helpers/typeof");Object.defineProperty(n,"__esModule",{value:!0}),n.chooseMethod=function(t){var e=[].concat(t.methods,u).filter(Boolean);if(t.type){if("simulate"===t.type)return s.default;var n=e.find(function(e){return e.type===t.type});if(n)return n;throw new Error("method-type "+t.type+" not found")}t.webWorkerSupport||a.isNode||(e=e.filter(function(e){return"idb"!==e.type}));e=e.find(function(e){return e.canBeUsed()});{if(e)return e;throw new Error("No useable method found in "+JSON.stringify(u.map(function(e){return e.type})))}};var o=r(e("./methods/native.js")),i=r(e("./methods/indexed-db.js")),n=r(e("./methods/localstorage.js")),s=r(e("./methods/simulate.js")),a=e("./util");var u=[o.default,i.default,n.default]},{"./methods/indexed-db.js":7,"./methods/localstorage.js":8,"./methods/native.js":9,"./methods/simulate.js":10,"./util":12,"@babel/runtime/helpers/interopRequireDefault":13,"@babel/runtime/helpers/typeof":14}],7:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.averageResponseTime=y,n.canBeUsed=w,n.cleanOldMessages=p,n.close=b,n.create=m,n.createDatabase=c,n.default=void 0,n.getAllMessages=function(e){var n=e.transaction(a).objectStore(a),r=[];return new Promise(function(t){n.openCursor().onsuccess=function(e){e=e.target.result;e?(r.push(e.value),e.continue()):t(r)}})},n.getIdb=u,n.getMessagesHigherThan=d,n.getOldMessages=h,n.microSeconds=void 0,n.onMessage=g,n.postMessage=_,n.removeMessageById=f,n.type=void 0,n.writeMessage=l;var o=e("../util.js"),i=e("oblivious-set"),s=e("../options"),e=o.microSeconds;n.microSeconds=e;var r="pubkey.broadcast-channel-0-",a="messages";function u(){if("undefined"!=typeof indexedDB)return indexedDB;if("undefined"!=typeof window){if(void 0!==window.mozIndexedDB)return window.mozIndexedDB;if(void 0!==window.webkitIndexedDB)return window.webkitIndexedDB;if(void 0!==window.msIndexedDB)return window.msIndexedDB}return!1}function c(e){var n=u().open(r+e,1);return n.onupgradeneeded=function(e){e.target.result.createObjectStore(a,{keyPath:"id",autoIncrement:!0})},new Promise(function(e,t){n.onerror=function(e){return t(e)},n.onsuccess=function(){e(n.result)}})}function l(e,t,n){var r={uuid:t,time:(new Date).getTime(),data:n},o=e.transaction([a],"readwrite");return new Promise(function(e,t){o.oncomplete=function(){return e()},o.onerror=function(e){return t(e)},o.objectStore(a).add(r)})}function d(e,n){var r=e.transaction(a).objectStore(a),o=[];return new Promise(function(t){(function(){try{var e=IDBKeyRange.bound(n+1,1/0);return r.openCursor(e)}catch(e){return r.openCursor()}})().onsuccess=function(e){e=e.target.result;e?e.value.idn.lastCursorId&&(n.lastCursorId=e.id),e}).filter(function(e){return t=n,(e=e).uuid!==t.uuid&&(!t.eMIs.has(e.id)&&!(e.data.time