@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.

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

+80 -2
+13
src/applications/config/controller/PhabricatorConfigClusterNotificationsController.php
··· 103 103 new PhutilNumber(idx($details, 'messages.in')), 104 104 new PhutilNumber(idx($details, 'messages.out'))); 105 105 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 + 106 115 } else { 107 116 $uptime = null; 108 117 $clients = null; 109 118 $stats = null; 119 + $history = null; 110 120 } 111 121 112 122 $status_view = array( ··· 126 136 $uptime, 127 137 $clients, 128 138 $stats, 139 + $history, 129 140 $messages, 130 141 ); 131 142 } ··· 143 154 pht('Uptime'), 144 155 pht('Clients'), 145 156 pht('Messages'), 157 + pht('History'), 146 158 null, 147 159 )) 148 160 ->setColumnClasses( 149 161 array( 162 + null, 150 163 null, 151 164 null, 152 165 null,
+67 -2
support/aphlict/server/lib/AphlictAdminServer.js
··· 17 17 server.on('request', JX.bind(this, this._onrequest)); 18 18 this._server = server; 19 19 this._clientServers = []; 20 + this._messageHistory = []; 20 21 }, 21 22 22 23 properties: { ··· 30 31 _messagesOut: null, 31 32 _server: null, 32 33 _startTime: null, 34 + _messageHistory: null, 33 35 34 36 getListenerLists: function(instance) { 35 37 var clients = this.getClientServers(); ··· 121 123 total_count += list.getTotalListenerCount(); 122 124 } 123 125 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 + 124 134 var server_status = { 125 135 'instance': instance, 126 - 'uptime': (new Date().getTime() - this._startTime), 136 + 'uptime': (now - this._startTime), 127 137 'clients.active': active_count, 128 138 'clients.total': total_count, 129 139 'messages.in': this._messagesIn, 130 140 'messages.out': this._messagesOut, 131 - 'version': 7 141 + 'version': 7, 142 + 'history.size': history_size, 143 + 'history.age': history_age 132 144 }; 133 145 134 146 response.writeHead(200, {'Content-Type': 'application/json'}); ··· 140 152 * Transmits a message to all subscribed listeners. 141 153 */ 142 154 _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 + 143 165 var peer_list = this.getPeerList(); 144 166 145 167 message = peer_list.addFingerprint(message); ··· 191 213 error); 192 214 } 193 215 } 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 + } 194 258 } 259 + 195 260 } 196 261 197 262 });