mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 03:20:59 +01:00
After Aphlict reconnects, ask the server to replay recent messages
Summary: Fixes T12563. If we've ever seen an "open", mark all future connections as reconnects. When we reconnect, replay recent history. (Until duplicate messages (T12564) are handled better this may cause some notification duplication.) Also emit a reconnect event (for T12566) but don't use it yet. Test Plan: {F4912044} Reviewers: chad Reviewed By: chad Maniphest Tasks: T12563 Differential Revision: https://secure.phabricator.com/D17708
This commit is contained in:
parent
88157a9442
commit
02194f0fc8
7 changed files with 130 additions and 29 deletions
|
@ -10,8 +10,8 @@ return array(
|
|||
'conpherence.pkg.css' => 'a34d59bd',
|
||||
'conpherence.pkg.js' => '5f86c17d',
|
||||
'core.pkg.css' => '959330a2',
|
||||
'core.pkg.js' => 'cb50c410',
|
||||
'darkconsole.pkg.js' => 'a2faee86',
|
||||
'core.pkg.js' => '1cedf416',
|
||||
'darkconsole.pkg.js' => '31272f61',
|
||||
'differential.pkg.css' => '90b30783',
|
||||
'differential.pkg.js' => 'ddfeb49b',
|
||||
'diffusion.pkg.css' => '91c5d3a6',
|
||||
|
@ -20,7 +20,7 @@ return array(
|
|||
'maniphest.pkg.css' => '4845691a',
|
||||
'maniphest.pkg.js' => '5ab2753f',
|
||||
'rsrc/css/aphront/aphront-bars.css' => '231ac33c',
|
||||
'rsrc/css/aphront/dark-console.css' => 'e7c6e44d',
|
||||
'rsrc/css/aphront/dark-console.css' => '53798a6d',
|
||||
'rsrc/css/aphront/dialog-view.css' => '685c7e2d',
|
||||
'rsrc/css/aphront/list-filter-view.css' => '5d6f0526',
|
||||
'rsrc/css/aphront/multi-column.css' => '84cc6640',
|
||||
|
@ -361,7 +361,7 @@ return array(
|
|||
'rsrc/image/texture/table_header.png' => '5c433037',
|
||||
'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
|
||||
'rsrc/image/texture/table_header_tall.png' => 'd56b434f',
|
||||
'rsrc/js/application/aphlict/Aphlict.js' => 'ce5f793f',
|
||||
'rsrc/js/application/aphlict/Aphlict.js' => '7cacce98',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-dropdown.js' => 'caade6f2',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'd82b1ff9',
|
||||
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '5e2634b9',
|
||||
|
@ -522,7 +522,7 @@ return array(
|
|||
'rsrc/js/core/behavior-workflow.js' => '0a3f3021',
|
||||
'rsrc/js/core/darkconsole/DarkLog.js' => 'c8e1ffe3',
|
||||
'rsrc/js/core/darkconsole/DarkMessage.js' => 'c48cccdd',
|
||||
'rsrc/js/core/darkconsole/behavior-dark-console.js' => '698614f9',
|
||||
'rsrc/js/core/darkconsole/behavior-dark-console.js' => '2a228a94',
|
||||
'rsrc/js/core/phtize.js' => 'd254d646',
|
||||
'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d',
|
||||
'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb',
|
||||
|
@ -538,7 +538,7 @@ return array(
|
|||
'symbols' => array(
|
||||
'almanac-css' => 'dbb9b3af',
|
||||
'aphront-bars' => '231ac33c',
|
||||
'aphront-dark-console-css' => 'e7c6e44d',
|
||||
'aphront-dark-console-css' => '53798a6d',
|
||||
'aphront-dialog-view-css' => '685c7e2d',
|
||||
'aphront-list-filter-view-css' => '5d6f0526',
|
||||
'aphront-multi-column-view-css' => '84cc6640',
|
||||
|
@ -583,7 +583,7 @@ return array(
|
|||
'herald-rule-editor' => 'd6a7e717',
|
||||
'herald-test-css' => 'a52e323e',
|
||||
'inline-comment-summary-css' => '51efda3a',
|
||||
'javelin-aphlict' => 'ce5f793f',
|
||||
'javelin-aphlict' => '7cacce98',
|
||||
'javelin-behavior' => '61cbc29a',
|
||||
'javelin-behavior-aphlict-dropdown' => 'caade6f2',
|
||||
'javelin-behavior-aphlict-listen' => 'd82b1ff9',
|
||||
|
@ -605,7 +605,7 @@ return array(
|
|||
'javelin-behavior-conpherence-pontificate' => '55616e04',
|
||||
'javelin-behavior-conpherence-search' => '9bbf3762',
|
||||
'javelin-behavior-countdown-timer' => 'e4cc26b3',
|
||||
'javelin-behavior-dark-console' => '698614f9',
|
||||
'javelin-behavior-dark-console' => '2a228a94',
|
||||
'javelin-behavior-dashboard-async-panel' => '469c0d9e',
|
||||
'javelin-behavior-dashboard-move-panels' => '408bf173',
|
||||
'javelin-behavior-dashboard-query-panel-select' => '453c5375',
|
||||
|
@ -1089,6 +1089,16 @@ return array(
|
|||
'javelin-install',
|
||||
'javelin-util',
|
||||
),
|
||||
'2a228a94' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
'javelin-util',
|
||||
'javelin-dom',
|
||||
'javelin-request',
|
||||
'phabricator-keyboard-shortcut',
|
||||
'phabricator-darklog',
|
||||
'phabricator-darkmessage',
|
||||
),
|
||||
'2b8de964' => array(
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
|
@ -1381,16 +1391,6 @@ return array(
|
|||
'6882e80a' => array(
|
||||
'javelin-dom',
|
||||
),
|
||||
'698614f9' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-stratcom',
|
||||
'javelin-util',
|
||||
'javelin-dom',
|
||||
'javelin-request',
|
||||
'phabricator-keyboard-shortcut',
|
||||
'phabricator-darklog',
|
||||
'phabricator-darkmessage',
|
||||
),
|
||||
'69adf288' => array(
|
||||
'javelin-install',
|
||||
),
|
||||
|
@ -1468,6 +1468,13 @@ return array(
|
|||
'owners-path-editor',
|
||||
'javelin-behavior',
|
||||
),
|
||||
'7cacce98' => array(
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
'javelin-websocket',
|
||||
'javelin-leader',
|
||||
'javelin-json',
|
||||
),
|
||||
'7cbe244b' => array(
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
|
@ -2014,13 +2021,6 @@ return array(
|
|||
'cd2b9b77' => array(
|
||||
'phui-oi-list-view-css',
|
||||
),
|
||||
'ce5f793f' => array(
|
||||
'javelin-install',
|
||||
'javelin-util',
|
||||
'javelin-websocket',
|
||||
'javelin-leader',
|
||||
'javelin-json',
|
||||
),
|
||||
'd0c516d5' => array(
|
||||
'javelin-behavior',
|
||||
'javelin-dom',
|
||||
|
|
|
@ -23,6 +23,7 @@ final class DarkConsoleRealtimePlugin extends DarkConsolePlugin {
|
|||
));
|
||||
|
||||
$reconnect_label = pht('Reconnect');
|
||||
$replay_label = pht('Replay');
|
||||
|
||||
$buttons = phutil_tag(
|
||||
'div',
|
||||
|
@ -40,11 +41,22 @@ final class DarkConsoleRealtimePlugin extends DarkConsolePlugin {
|
|||
'action' => 'reconnect',
|
||||
'label' => $reconnect_label,
|
||||
)),
|
||||
id(new PHUIButtonView())
|
||||
->setIcon('fa-backward')
|
||||
->setColor(PHUIButtonView::GREY)
|
||||
->setText($replay_label)
|
||||
->addSigil('dark-console-realtime-action')
|
||||
->setMetadata(
|
||||
array(
|
||||
'action' => 'replay',
|
||||
'label' => $replay_label,
|
||||
)),
|
||||
));
|
||||
|
||||
return phutil_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'dark-console-realtime',
|
||||
),
|
||||
array(
|
||||
$buttons,
|
||||
|
|
|
@ -197,3 +197,8 @@ for (ii = 0; ii < aphlict_admins.length; ii++) {
|
|||
admin_server.setClientServers(aphlict_clients);
|
||||
admin_server.setPeerList(peer_list);
|
||||
}
|
||||
|
||||
for (ii = 0; ii < aphlict_clients.length; ii++) {
|
||||
var client_server = aphlict_clients[ii];
|
||||
client_server.setAdminServers(aphlict_admins);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@ JX.install('AphlictClientServer', {
|
|||
|
||||
this._server = server;
|
||||
this._lists = {};
|
||||
this._adminServers = [];
|
||||
},
|
||||
|
||||
properties: {
|
||||
logger: null,
|
||||
adminServers: null
|
||||
},
|
||||
|
||||
members: {
|
||||
|
@ -33,6 +35,20 @@ JX.install('AphlictClientServer', {
|
|||
return this._lists[instance];
|
||||
},
|
||||
|
||||
getHistory: function(age) {
|
||||
var results = [];
|
||||
|
||||
var servers = this.getAdminServers();
|
||||
for (var ii = 0; ii < servers.length; ii++) {
|
||||
var messages = servers[ii].getHistory(age);
|
||||
for (var jj = 0; jj < messages.length; jj++) {
|
||||
results.push(messages[jj]);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
log: function() {
|
||||
var logger = this.getLogger();
|
||||
if (!logger) {
|
||||
|
@ -117,6 +133,26 @@ JX.install('AphlictClientServer', {
|
|||
listener.unsubscribe(message.data);
|
||||
break;
|
||||
|
||||
case 'replay':
|
||||
var age = message.data.age || 60000;
|
||||
var min_age = (new Date().getTime() - age);
|
||||
|
||||
var old_messages = self.getHistory(min_age);
|
||||
for (var ii = 0; ii < old_messages.length; ii++) {
|
||||
var old_message = old_messages[ii];
|
||||
|
||||
if (!listener.isSubscribedToAny(old_message.subscribers)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
listener.writeMessage(old_message);
|
||||
} catch (error) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log(
|
||||
'Unrecognized command "%s".',
|
||||
|
|
|
@ -231,3 +231,7 @@
|
|||
padding: 8px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.dark-console-realtime .button {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ JX.install('Aphlict', {
|
|||
_socket: null,
|
||||
_subscriptions: null,
|
||||
_status: null,
|
||||
_isReconnect: false,
|
||||
|
||||
start: function() {
|
||||
JX.Leader.listen('onBecomeLeader', JX.bind(this, this._lead));
|
||||
|
@ -94,10 +95,31 @@ JX.install('Aphlict', {
|
|||
},
|
||||
|
||||
_open: function() {
|
||||
// If this is a reconnect, ask the server to replay recent messages
|
||||
// after other tabs have had a chance to subscribe. Do this before we
|
||||
// broadcast that the connection status is now open.
|
||||
if (this._isReconnect) {
|
||||
setTimeout(JX.bind(this, this._reconnect), 100);
|
||||
}
|
||||
|
||||
this._broadcastStatus('open');
|
||||
JX.Leader.broadcast(null, {type: 'aphlict.getsubscribers'});
|
||||
},
|
||||
|
||||
_reconnect: function() {
|
||||
this.replay();
|
||||
|
||||
JX.Leader.broadcast(null, {type: 'aphlict.reconnect', data: null});
|
||||
},
|
||||
|
||||
replay: function() {
|
||||
var replay = {
|
||||
age: 60000
|
||||
};
|
||||
|
||||
JX.Leader.broadcast(null, {type: 'aphlict.replay', data: replay});
|
||||
},
|
||||
|
||||
_close: function() {
|
||||
this._broadcastStatus('closed');
|
||||
},
|
||||
|
@ -131,10 +153,13 @@ JX.install('Aphlict', {
|
|||
|
||||
case 'aphlict.subscribe':
|
||||
if (is_leader) {
|
||||
this._write({
|
||||
command: 'subscribe',
|
||||
data: message.data
|
||||
});
|
||||
this._writeCommand('subscribe', message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'aphlict.replay':
|
||||
if (is_leader) {
|
||||
this._writeCommand('replay', message.data);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -147,11 +172,27 @@ JX.install('Aphlict', {
|
|||
|
||||
_setStatus: function(status) {
|
||||
this._status = status;
|
||||
|
||||
// If we've ever seen an open connection, any new connection we make
|
||||
// is a reconnect and should replay history.
|
||||
if (status == 'open') {
|
||||
this._isReconnect = true;
|
||||
}
|
||||
|
||||
this.invoke('didChangeStatus');
|
||||
},
|
||||
|
||||
_write: function(message) {
|
||||
this._socket.send(JX.JSON.stringify(message));
|
||||
},
|
||||
|
||||
_writeCommand: function(command, message) {
|
||||
var frame = {
|
||||
command: command,
|
||||
data: message
|
||||
};
|
||||
|
||||
return this._write(frame);
|
||||
}
|
||||
|
||||
},
|
||||
|
|
|
@ -392,6 +392,9 @@ JX.behavior('dark-console', function(config, statics) {
|
|||
ws.reconnect();
|
||||
}
|
||||
break;
|
||||
case 'replay':
|
||||
JX.Aphlict.getInstance().replay();
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue