1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-19 16:58:48 +02: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:
epriestley 2017-04-17 14:05:29 -07:00
parent 88157a9442
commit 02194f0fc8
7 changed files with 130 additions and 29 deletions

View file

@ -10,8 +10,8 @@ return array(
'conpherence.pkg.css' => 'a34d59bd', 'conpherence.pkg.css' => 'a34d59bd',
'conpherence.pkg.js' => '5f86c17d', 'conpherence.pkg.js' => '5f86c17d',
'core.pkg.css' => '959330a2', 'core.pkg.css' => '959330a2',
'core.pkg.js' => 'cb50c410', 'core.pkg.js' => '1cedf416',
'darkconsole.pkg.js' => 'a2faee86', 'darkconsole.pkg.js' => '31272f61',
'differential.pkg.css' => '90b30783', 'differential.pkg.css' => '90b30783',
'differential.pkg.js' => 'ddfeb49b', 'differential.pkg.js' => 'ddfeb49b',
'diffusion.pkg.css' => '91c5d3a6', 'diffusion.pkg.css' => '91c5d3a6',
@ -20,7 +20,7 @@ return array(
'maniphest.pkg.css' => '4845691a', 'maniphest.pkg.css' => '4845691a',
'maniphest.pkg.js' => '5ab2753f', 'maniphest.pkg.js' => '5ab2753f',
'rsrc/css/aphront/aphront-bars.css' => '231ac33c', '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/dialog-view.css' => '685c7e2d',
'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526',
'rsrc/css/aphront/multi-column.css' => '84cc6640', '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.png' => '5c433037',
'rsrc/image/texture/table_header_hover.png' => '038ec3b9', 'rsrc/image/texture/table_header_hover.png' => '038ec3b9',
'rsrc/image/texture/table_header_tall.png' => 'd56b434f', '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-dropdown.js' => 'caade6f2',
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'd82b1ff9', 'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'd82b1ff9',
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => '5e2634b9', '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/behavior-workflow.js' => '0a3f3021',
'rsrc/js/core/darkconsole/DarkLog.js' => 'c8e1ffe3', 'rsrc/js/core/darkconsole/DarkLog.js' => 'c8e1ffe3',
'rsrc/js/core/darkconsole/DarkMessage.js' => 'c48cccdd', '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/core/phtize.js' => 'd254d646',
'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d',
'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb', 'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb',
@ -538,7 +538,7 @@ return array(
'symbols' => array( 'symbols' => array(
'almanac-css' => 'dbb9b3af', 'almanac-css' => 'dbb9b3af',
'aphront-bars' => '231ac33c', 'aphront-bars' => '231ac33c',
'aphront-dark-console-css' => 'e7c6e44d', 'aphront-dark-console-css' => '53798a6d',
'aphront-dialog-view-css' => '685c7e2d', 'aphront-dialog-view-css' => '685c7e2d',
'aphront-list-filter-view-css' => '5d6f0526', 'aphront-list-filter-view-css' => '5d6f0526',
'aphront-multi-column-view-css' => '84cc6640', 'aphront-multi-column-view-css' => '84cc6640',
@ -583,7 +583,7 @@ return array(
'herald-rule-editor' => 'd6a7e717', 'herald-rule-editor' => 'd6a7e717',
'herald-test-css' => 'a52e323e', 'herald-test-css' => 'a52e323e',
'inline-comment-summary-css' => '51efda3a', 'inline-comment-summary-css' => '51efda3a',
'javelin-aphlict' => 'ce5f793f', 'javelin-aphlict' => '7cacce98',
'javelin-behavior' => '61cbc29a', 'javelin-behavior' => '61cbc29a',
'javelin-behavior-aphlict-dropdown' => 'caade6f2', 'javelin-behavior-aphlict-dropdown' => 'caade6f2',
'javelin-behavior-aphlict-listen' => 'd82b1ff9', 'javelin-behavior-aphlict-listen' => 'd82b1ff9',
@ -605,7 +605,7 @@ return array(
'javelin-behavior-conpherence-pontificate' => '55616e04', 'javelin-behavior-conpherence-pontificate' => '55616e04',
'javelin-behavior-conpherence-search' => '9bbf3762', 'javelin-behavior-conpherence-search' => '9bbf3762',
'javelin-behavior-countdown-timer' => 'e4cc26b3', 'javelin-behavior-countdown-timer' => 'e4cc26b3',
'javelin-behavior-dark-console' => '698614f9', 'javelin-behavior-dark-console' => '2a228a94',
'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-async-panel' => '469c0d9e',
'javelin-behavior-dashboard-move-panels' => '408bf173', 'javelin-behavior-dashboard-move-panels' => '408bf173',
'javelin-behavior-dashboard-query-panel-select' => '453c5375', 'javelin-behavior-dashboard-query-panel-select' => '453c5375',
@ -1089,6 +1089,16 @@ return array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
), ),
'2a228a94' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-util',
'javelin-dom',
'javelin-request',
'phabricator-keyboard-shortcut',
'phabricator-darklog',
'phabricator-darkmessage',
),
'2b8de964' => array( '2b8de964' => array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
@ -1381,16 +1391,6 @@ return array(
'6882e80a' => array( '6882e80a' => array(
'javelin-dom', 'javelin-dom',
), ),
'698614f9' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-util',
'javelin-dom',
'javelin-request',
'phabricator-keyboard-shortcut',
'phabricator-darklog',
'phabricator-darkmessage',
),
'69adf288' => array( '69adf288' => array(
'javelin-install', 'javelin-install',
), ),
@ -1468,6 +1468,13 @@ return array(
'owners-path-editor', 'owners-path-editor',
'javelin-behavior', 'javelin-behavior',
), ),
'7cacce98' => array(
'javelin-install',
'javelin-util',
'javelin-websocket',
'javelin-leader',
'javelin-json',
),
'7cbe244b' => array( '7cbe244b' => array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',
@ -2014,13 +2021,6 @@ return array(
'cd2b9b77' => array( 'cd2b9b77' => array(
'phui-oi-list-view-css', 'phui-oi-list-view-css',
), ),
'ce5f793f' => array(
'javelin-install',
'javelin-util',
'javelin-websocket',
'javelin-leader',
'javelin-json',
),
'd0c516d5' => array( 'd0c516d5' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-dom', 'javelin-dom',

View file

@ -23,6 +23,7 @@ final class DarkConsoleRealtimePlugin extends DarkConsolePlugin {
)); ));
$reconnect_label = pht('Reconnect'); $reconnect_label = pht('Reconnect');
$replay_label = pht('Replay');
$buttons = phutil_tag( $buttons = phutil_tag(
'div', 'div',
@ -40,11 +41,22 @@ final class DarkConsoleRealtimePlugin extends DarkConsolePlugin {
'action' => 'reconnect', 'action' => 'reconnect',
'label' => $reconnect_label, '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( return phutil_tag(
'div', 'div',
array( array(
'class' => 'dark-console-realtime',
), ),
array( array(
$buttons, $buttons,

View file

@ -197,3 +197,8 @@ for (ii = 0; ii < aphlict_admins.length; ii++) {
admin_server.setClientServers(aphlict_clients); admin_server.setClientServers(aphlict_clients);
admin_server.setPeerList(peer_list); admin_server.setPeerList(peer_list);
} }
for (ii = 0; ii < aphlict_clients.length; ii++) {
var client_server = aphlict_clients[ii];
client_server.setAdminServers(aphlict_admins);
}

View file

@ -16,10 +16,12 @@ JX.install('AphlictClientServer', {
this._server = server; this._server = server;
this._lists = {}; this._lists = {};
this._adminServers = [];
}, },
properties: { properties: {
logger: null, logger: null,
adminServers: null
}, },
members: { members: {
@ -33,6 +35,20 @@ JX.install('AphlictClientServer', {
return this._lists[instance]; 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() { log: function() {
var logger = this.getLogger(); var logger = this.getLogger();
if (!logger) { if (!logger) {
@ -117,6 +133,26 @@ JX.install('AphlictClientServer', {
listener.unsubscribe(message.data); listener.unsubscribe(message.data);
break; 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: default:
log( log(
'Unrecognized command "%s".', 'Unrecognized command "%s".',

View file

@ -231,3 +231,7 @@
padding: 8px; padding: 8px;
margin: 2px; margin: 2px;
} }
.dark-console-realtime .button {
margin-right: 8px;
}

View file

@ -40,6 +40,7 @@ JX.install('Aphlict', {
_socket: null, _socket: null,
_subscriptions: null, _subscriptions: null,
_status: null, _status: null,
_isReconnect: false,
start: function() { start: function() {
JX.Leader.listen('onBecomeLeader', JX.bind(this, this._lead)); JX.Leader.listen('onBecomeLeader', JX.bind(this, this._lead));
@ -94,10 +95,31 @@ JX.install('Aphlict', {
}, },
_open: function() { _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'); this._broadcastStatus('open');
JX.Leader.broadcast(null, {type: 'aphlict.getsubscribers'}); 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() { _close: function() {
this._broadcastStatus('closed'); this._broadcastStatus('closed');
}, },
@ -131,10 +153,13 @@ JX.install('Aphlict', {
case 'aphlict.subscribe': case 'aphlict.subscribe':
if (is_leader) { if (is_leader) {
this._write({ this._writeCommand('subscribe', message.data);
command: 'subscribe', }
data: message.data break;
});
case 'aphlict.replay':
if (is_leader) {
this._writeCommand('replay', message.data);
} }
break; break;
@ -147,11 +172,27 @@ JX.install('Aphlict', {
_setStatus: function(status) { _setStatus: function(status) {
this._status = 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'); this.invoke('didChangeStatus');
}, },
_write: function(message) { _write: function(message) {
this._socket.send(JX.JSON.stringify(message)); this._socket.send(JX.JSON.stringify(message));
},
_writeCommand: function(command, message) {
var frame = {
command: command,
data: message
};
return this._write(frame);
} }
}, },

View file

@ -392,6 +392,9 @@ JX.behavior('dark-console', function(config, statics) {
ws.reconnect(); ws.reconnect();
} }
break; break;
case 'replay':
JX.Aphlict.getInstance().replay();
break;
} }
}); });