Skip to content

Commit 88157a9

Browse files
author
epriestley
committedApr 17, 2017
Hold recent messages in Aphlict so they can be replayed after clients reconnect
Summary: Ref T12563. Before broadcasting messages from the server, store them in a history buffer. A future change will let clients retrieve them. Test Plan: - Used the web frontend to look at the buffer, reloaded over time, sent messages. Saw buffer size go up as I sent messages and fall after 60 seconds. - Set size to 4 messages, sent a bunch of messages, saw the buffer size max out at 4 messages. Reviewers: chad Reviewed By: chad Maniphest Tasks: T12563 Differential Revision: https://secure.phabricator.com/D17707
1 parent 8fdc1bf commit 88157a9

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed
 

‎src/applications/config/controller/PhabricatorConfigClusterNotificationsController.php

+13
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,20 @@ private function buildClusterNotificationStatus() {
103103
new PhutilNumber(idx($details, 'messages.in')),
104104
new PhutilNumber(idx($details, 'messages.out')));
105105

106+
if (idx($details, 'history.size')) {
107+
$history = pht(
108+
'%s Held / %sms',
109+
new PhutilNumber(idx($details, 'history.size')),
110+
new PhutilNumber(idx($details, 'history.age')));
111+
} else {
112+
$history = pht('No Messages');
113+
}
114+
106115
} else {
107116
$uptime = null;
108117
$clients = null;
109118
$stats = null;
119+
$history = null;
110120
}
111121

112122
$status_view = array(
@@ -126,6 +136,7 @@ private function buildClusterNotificationStatus() {
126136
$uptime,
127137
$clients,
128138
$stats,
139+
$history,
129140
$messages,
130141
);
131142
}
@@ -143,6 +154,7 @@ private function buildClusterNotificationStatus() {
143154
pht('Uptime'),
144155
pht('Clients'),
145156
pht('Messages'),
157+
pht('History'),
146158
null,
147159
))
148160
->setColumnClasses(
@@ -155,6 +167,7 @@ private function buildClusterNotificationStatus() {
155167
null,
156168
null,
157169
null,
170+
null,
158171
'wide',
159172
));
160173

‎support/aphlict/server/lib/AphlictAdminServer.js

+67-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ JX.install('AphlictAdminServer', {
1717
server.on('request', JX.bind(this, this._onrequest));
1818
this._server = server;
1919
this._clientServers = [];
20+
this._messageHistory = [];
2021
},
2122

2223
properties: {
@@ -30,6 +31,7 @@ JX.install('AphlictAdminServer', {
3031
_messagesOut: null,
3132
_server: null,
3233
_startTime: null,
34+
_messageHistory: null,
3335

3436
getListenerLists: function(instance) {
3537
var clients = this.getClientServers();
@@ -121,14 +123,24 @@ JX.install('AphlictAdminServer', {
121123
total_count += list.getTotalListenerCount();
122124
}
123125

126+
var now = new Date().getTime();
127+
128+
var history_size = this._messageHistory.length;
129+
var history_age = null;
130+
if (history_size) {
131+
history_age = (now - this._messageHistory[0].timestamp);
132+
}
133+
124134
var server_status = {
125135
'instance': instance,
126-
'uptime': (new Date().getTime() - this._startTime),
136+
'uptime': (now - this._startTime),
127137
'clients.active': active_count,
128138
'clients.total': total_count,
129139
'messages.in': this._messagesIn,
130140
'messages.out': this._messagesOut,
131-
'version': 7
141+
'version': 7,
142+
'history.size': history_size,
143+
'history.age': history_age
132144
};
133145

134146
response.writeHead(200, {'Content-Type': 'application/json'});
@@ -140,6 +152,16 @@ JX.install('AphlictAdminServer', {
140152
* Transmits a message to all subscribed listeners.
141153
*/
142154
_transmit: function(instance, message, response) {
155+
var now = new Date().getTime();
156+
157+
this._messageHistory.push(
158+
{
159+
timestamp: now,
160+
message: message
161+
});
162+
163+
this._purgeHistory();
164+
143165
var peer_list = this.getPeerList();
144166

145167
message = peer_list.addFingerprint(message);
@@ -191,7 +213,50 @@ JX.install('AphlictAdminServer', {
191213
error);
192214
}
193215
}
216+
},
217+
218+
getHistory: function(min_age) {
219+
var history = this._messageHistory;
220+
var results = [];
221+
222+
for (var ii = 0; ii < history.length; ii++) {
223+
if (history[ii].timestamp >= min_age) {
224+
results.push(history[ii].message);
225+
}
226+
}
227+
228+
return results;
229+
},
230+
231+
_purgeHistory: function() {
232+
var messages = this._messageHistory;
233+
234+
// Maximum number of messages to retain.
235+
var size_limit = 4096;
236+
237+
// Find the index of the first item we're going to keep. If we have too
238+
// many items, this will be somewhere past the beginning of the list.
239+
var keep = Math.max(0, messages.length - size_limit);
240+
241+
// Maximum number of milliseconds of history to retain.
242+
var age_limit = 60000;
243+
244+
// Move the index forward until we find an item that is recent enough
245+
// to retain.
246+
var now = new Date().getTime();
247+
var min_age = (now - age_limit);
248+
for (keep; keep < messages.length; keep++) {
249+
if (messages[keep].timestamp >= min_age) {
250+
break;
251+
}
252+
}
253+
254+
// Throw away extra messages.
255+
if (keep) {
256+
this._messageHistory.splice(0, keep);
257+
}
194258
}
259+
195260
}
196261

197262
});

0 commit comments

Comments
 (0)
Failed to load comments.