@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Probably improve behavior around duplicate notifications

Summary:
We're sometimes getting duplicate notifications right now. I think this is because multiple windows are racing and becoming leaders.

Clean this up a little:

- Fix the `timeoout` typo.
- Only try to usurp once.
- Use different usurp and expire delays, so we don't fire them at the exact same time.

Not sure if this'll work or not but it should theoretically be a little cleaner.

Test Plan:
- Quit Safari, reopened Safari, still saw a fast reconnect to the notification server (this is the goal of usurping).
- Did normal notification stuff like opening a chat in two windows, got notifications.
- Hard to reproduce the race for sure, but this at least fixes the outright `timeoout` bug.

Reviewers: chad

Reviewed By: chad

Differential Revision: https://secure.phabricator.com/D15806

+22 -15
+6 -6
resources/celerity/map.php
··· 8 8 return array( 9 9 'names' => array( 10 10 'core.pkg.css' => '04a95108', 11 - 'core.pkg.js' => '37344f3c', 11 + 'core.pkg.js' => '6972d365', 12 12 'darkconsole.pkg.js' => 'e7393ebb', 13 13 'differential.pkg.css' => '7ba78475', 14 14 'differential.pkg.js' => 'd0cd0df6', ··· 232 232 'rsrc/externals/javelin/lib/DOM.js' => '805b806a', 233 233 'rsrc/externals/javelin/lib/History.js' => 'd4505101', 234 234 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 235 - 'rsrc/externals/javelin/lib/Leader.js' => 'b4ba945c', 235 + 'rsrc/externals/javelin/lib/Leader.js' => 'fea0eb47', 236 236 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', 237 237 'rsrc/externals/javelin/lib/Quicksand.js' => '6b8ef10b', 238 238 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', ··· 704 704 'javelin-history' => 'd4505101', 705 705 'javelin-install' => '05270951', 706 706 'javelin-json' => '69adf288', 707 - 'javelin-leader' => 'b4ba945c', 707 + 'javelin-leader' => 'fea0eb47', 708 708 'javelin-magical-init' => '3010e992', 709 709 'javelin-mask' => '8a41885b', 710 710 'javelin-quicksand' => '6b8ef10b', ··· 1772 1772 'javelin-typeahead-preloaded-source', 1773 1773 'javelin-util', 1774 1774 ), 1775 - 'b4ba945c' => array( 1776 - 'javelin-install', 1777 - ), 1778 1775 'b59e1e96' => array( 1779 1776 'javelin-behavior', 1780 1777 'javelin-stratcom', ··· 2175 2172 'javelin-dom', 2176 2173 'javelin-view-visitor', 2177 2174 'javelin-util', 2175 + ), 2176 + 'fea0eb47' => array( 2177 + 'javelin-install', 2178 2178 ), 2179 2179 ), 2180 2180 'packages' => array(
+16 -9
webroot/rsrc/externals/javelin/lib/Leader.js
··· 118 118 // Read the current leadership lease. 119 119 var lease = self._read(); 120 120 121 + // Stagger these delays so that they are unlikely to race one another. 122 + var expire_delay = 50; 123 + var usurp_delay = 75; 124 + 121 125 // If the lease is good, we're all set. 122 126 var now = +new Date(); 123 127 if (lease.until > now) { ··· 135 139 } else { 136 140 137 141 // Set a callback to try to become the leader shortly after the 138 - // current lease expires. This lets us recover from cases where the 139 - // leader goes missing quickly. 140 - if (self._timeoout) { 141 - window.clearTimeout(self._timeout); 142 - self._timeout = null; 142 + // current lease expires. This lets us quickly recover from cases 143 + // where the leader goes missing. 144 + 145 + // In particular, this can happen in Safari if you close windows or 146 + // quit the browser instead of browsing away: the "pagehide" event 147 + // does not fire when the leader is simply destroyed, so it does not 148 + // evict itself from the throne of power. 149 + if (!self._timeout) { 150 + var usurp_at = (lease.until - now) + usurp_delay; 151 + self._timeout = window.setTimeout(self._usurp, usurp_at); 143 152 } 144 - self._timeout = window.setTimeout( 145 - self._usurp, 146 - (lease.until - now) + 50); 147 153 148 154 follower_callback(); 149 155 } ··· 174 180 175 181 window.setTimeout( 176 182 JX.bind(null, self._callIf, leader_callback, follower_callback), 177 - 50); 183 + expire_delay); 178 184 }, 179 185 180 186 ··· 306 312 _usurp: function() { 307 313 var self = JX.Leader; 308 314 self.call(JX.bag); 315 + self._timeout = null; 309 316 }, 310 317 311 318