Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/externals/javelin/lib/Leader.js
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | statics: { | ||||
_seenList: [], | _seenList: [], | ||||
/** | /** | ||||
* Elect a leader, triggering leadership callbacks if they are registered. | * Elect a leader, triggering leadership callbacks if they are registered. | ||||
*/ | */ | ||||
start: function() { | start: function() { | ||||
var self = JX.Leader; | var self = JX.Leader; | ||||
self.callIfLeader(JX.bag); | self.call(JX.bag); | ||||
}, | }, | ||||
/** | /** | ||||
* Call a method if this tab is the leader. | * Call a method if this tab is the leader. | ||||
* | * | ||||
* This is asynchronous because leadership election is asynchronous. If | * This is asynchronous because leadership election is asynchronous. If | ||||
* the current tab is not the leader after any election takes place, the | * the current tab is not the leader after any election takes place, the | ||||
* callback will not be invoked. | * callback will not be invoked. | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | _callIf: function(leader_callback, follower_callback) { | ||||
// tab is closed. | // tab is closed. | ||||
if (!self._interval && lease.until > now + 10000) { | if (!self._interval && lease.until > now + 10000) { | ||||
self._interval = window.setInterval(self._write, 5000); | self._interval = window.setInterval(self._write, 5000); | ||||
} | } | ||||
self._becomeLeader(); | self._becomeLeader(); | ||||
leader_callback(); | leader_callback(); | ||||
} else { | } else { | ||||
// Set a callback to try to become the leader shortly after the | |||||
// current lease expires. This lets us recover from cases where the | |||||
// leader goes missing quickly. | |||||
window.setTimeout(self._usurp, (lease.until - now) + 50); | |||||
follower_callback(); | follower_callback(); | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
// If the lease isn't good, try to become the leader. We don't have | // If the lease isn't good, try to become the leader. We don't have | ||||
// proper locking primitives for this, but can do a relatively good | // proper locking primitives for this, but can do a relatively good | ||||
// job. The algorithm here is: | // job. The algorithm here is: | ||||
// | // | ||||
// - Write our ID, trying to acquire the lease. | // - Write our ID, trying to acquire the lease. | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | _becomeLeader: function() { | ||||
if (self._isLeader) { | if (self._isLeader) { | ||||
return; | return; | ||||
} | } | ||||
self._isLeader = true; | self._isLeader = true; | ||||
new JX.Leader().invoke('onBecomeLeader'); | new JX.Leader().invoke('onBecomeLeader'); | ||||
}, | }, | ||||
/** | |||||
* Try to usurp leadership position after a lease expiration. | |||||
*/ | |||||
_usurp: function() { | |||||
var self = JX.Leader; | |||||
self.call(JX.bag); | |||||
}, | |||||
/** | /** | ||||
* Mark a message as seen. | * Mark a message as seen. | ||||
* | * | ||||
* We keep a fixed-sized list of recent messages, and let old ones fall | * We keep a fixed-sized list of recent messages, and let old ones fall | ||||
* off the end after a while. | * off the end after a while. | ||||
*/ | */ | ||||
_markSeen: function(id) { | _markSeen: function(id) { | ||||
var self = JX.Leader; | var self = JX.Leader; | ||||
Show All 11 Lines |