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

Break some of Aphlict into reasonable classes with sensible responsibilities

Summary:
Ref T4324.

- Create `Listener` to represent listening clients.
- Create `ListenerList` to represent the current list of clients.
- Create `Logfile` to handle logging.

Test Plan: Clicked "Send Test Notification", verified logs, status and notifications all work correctly.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4324

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

+204 -80
+1 -1
resources/celerity/map.php
··· 170 170 'rsrc/externals/javelin/core/__tests__/stratcom.js' => 'da194d4b', 171 171 'rsrc/externals/javelin/core/__tests__/util.js' => 'd3b157a9', 172 172 'rsrc/externals/javelin/core/init.js' => 'b88ab49e', 173 - 'rsrc/externals/javelin/core/init_node.js' => '9fe4895f', 173 + 'rsrc/externals/javelin/core/init_node.js' => 'd7dde471', 174 174 'rsrc/externals/javelin/core/install.js' => '52a92793', 175 175 'rsrc/externals/javelin/core/util.js' => '7501647b', 176 176 'rsrc/externals/javelin/docs/Base.js' => '3b9ca7eb',
+35 -57
support/aphlict/server/aphlict_server.js
··· 7 7 */ 8 8 9 9 var JX = require('./lib/javelin').JX; 10 - JX.require('lib/AphlictIDGenerator', __dirname); 10 + 11 + JX.require('lib/AphlictListenerList', __dirname); 12 + JX.require('lib/AphlictLog', __dirname); 13 + 14 + var debug = new JX.AphlictLog() 15 + .addConsole(console); 11 16 12 - var id_generator = new JX.AphlictIDGenerator(); 17 + var clients = new JX.AphlictListenerList(); 13 18 14 19 var config = parse_command_line_arguments(process.argv); 20 + 21 + if (config.logfile) { 22 + debug.addLogfile(config.logfile); 23 + } 15 24 16 25 function parse_command_line_arguments(argv) { 17 26 var config = { ··· 54 63 var http = require('http'); 55 64 var url = require('url'); 56 65 var querystring = require('querystring'); 57 - var fs = require('fs'); 58 66 59 - // set up log file 60 - var logfile = fs.createWriteStream( 61 - config.log, 62 - { 63 - flags: 'a', 64 - encoding: null, 65 - mode: 0666 66 - }); 67 - 68 - function log(str) { 69 - console.log(str); 70 - logfile.write(str + '\n'); 71 - } 72 67 73 68 process.on('uncaughtException', function (err) { 74 69 log("\n<<< UNCAUGHT EXCEPTION! >>>\n\n" + err); 75 70 process.exit(1); 76 71 }); 77 - 78 - log('----- ' + (new Date()).toLocaleString() + ' -----\n'); 79 72 80 73 function getFlashPolicy() { 81 74 return [ ··· 92 85 socket.write(getFlashPolicy() + '\0'); 93 86 socket.end(); 94 87 95 - log('[' + socket.remoteAddress + '] Sent Flash Policy'); 88 + debug.log('[' + socket.remoteAddress + '] Sent Flash Policy'); 96 89 97 90 socket.on('error', function (e) { 98 - log('Error in policy server: ' + e); 91 + debug.log('Error in policy server: ' + e); 99 92 }); 100 93 }).listen(843); 101 94 102 95 103 - function write_json(socket, data) { 104 - var serial = JSON.stringify(data); 105 - var length = Buffer.byteLength(serial, 'utf8'); 106 - length = length.toString(); 107 - while (length.length < 8) { 108 - length = '0' + length; 109 - } 110 - socket.write(length + serial); 111 - } 112 - 113 - 114 - var clients = {}; 115 - var current_connections = 0; 116 - 117 96 var send_server = net.createServer(function(socket) { 118 - var client_id = id_generator.generateNext(); 119 - var client_name = '[' + socket.remoteAddress + '] [#' + client_id + '] '; 97 + var listener = clients.addListener(socket); 120 98 121 - clients[client_id] = socket; 122 - current_connections++; 123 - log(client_name + 'connected\t\t(' + 124 - current_connections + ' current connections)'); 99 + debug.log('<%s> Connected from %s', 100 + listener.getDescription(), 101 + socket.remoteAddress); 125 102 126 103 socket.on('close', function() { 127 - delete clients[client_id]; 128 - current_connections--; 129 - log(client_name + 'closed\t\t(' + 130 - current_connections + ' current connections)'); 104 + clients.removeListener(listener); 105 + debug.log('<%s> Disconnected', listener.getDescription()); 131 106 }); 132 107 133 108 socket.on('timeout', function() { 134 - log(client_name + 'timed out!'); 109 + debug.log('<%s> Timed Out', listener.getDescription()); 135 110 }); 136 111 137 112 socket.on('end', function() { 138 - log(client_name + 'ended the connection'); 139 - // node automatically closes half-open connections 113 + debug.log('<%s> Ended Connection', listener.getDescription()); 140 114 }); 141 115 142 116 socket.on('error', function (e) { 143 - log(client_name + 'Uncaught error in send server: ' + e); 117 + debug.log('<%s> Error: %s', listener.getDescription(), e); 144 118 }); 119 + 145 120 }).listen(config.port); 146 121 147 122 ··· 164 139 ++messages_in; 165 140 166 141 var data = querystring.parse(body); 167 - log('notification: ' + JSON.stringify(data)); 142 + debug.log('notification: ' + JSON.stringify(data)); 168 143 broadcast(data); 169 144 response.end(); 170 145 }); ··· 177 152 request.on('end', function() { 178 153 var status = { 179 154 'uptime': (new Date().getTime() - start_time), 180 - 'clients.active': current_connections, 181 - 'clients.total': id_generator.getTotalCount(), 155 + 'clients.active': clients.getActiveListenerCount(), 156 + 'clients.total': clients.getTotalListenerCount(), 182 157 'messages.in': messages_in, 183 158 'messages.out': messages_out, 184 159 'log': config.log, ··· 197 172 }).listen(config.admin, config.host); 198 173 199 174 function broadcast(data) { 200 - for (var client_id in clients) { 175 + var listeners = clients.getListeners(); 176 + for (var id in listeners) { 177 + var listener = listeners[id]; 201 178 try { 202 - write_json(clients[client_id], data); 179 + listener.writeMessage(data); 180 + 203 181 ++messages_out; 204 - log('wrote to client ' + client_id); 182 + debug.log('<%s> Wrote Message', listener.getDescription()); 205 183 } catch (error) { 206 - delete clients[client_id]; 207 - current_connections--; 208 - log('ERROR: could not write to client ' + client_id); 184 + clients.removeListener(listener); 185 + debug.log('<%s> Write Error: %s', error); 209 186 } 210 187 } 211 188 } ··· 216 193 process.setuid(config.user); 217 194 } 218 195 196 + debug.log('Started Server (PID %d)', process.pid);
-18
support/aphlict/server/lib/AphlictIDGenerator.js
··· 1 - var JX = require('javelin').JX; 2 - 3 - JX.install('AphlictIDGenerator', { 4 - 5 - members : { 6 - _next : 0, 7 - 8 - generateNext : function() { 9 - this._next = ((this._next + 1) % 1000000000000); 10 - return this._next; 11 - }, 12 - 13 - getTotalCount : function() { 14 - return this._next; 15 - } 16 - } 17 - 18 - });
+39
support/aphlict/server/lib/AphlictListener.js
··· 1 + var JX = require('javelin').JX; 2 + 3 + JX.install('AphlictListener', { 4 + construct : function(id, socket) { 5 + this._id = id; 6 + this._socket = socket; 7 + }, 8 + 9 + members : { 10 + _id : null, 11 + _socket : null, 12 + 13 + getID : function() { 14 + return this._id; 15 + }, 16 + 17 + getSocket : function() { 18 + return this._socket; 19 + }, 20 + 21 + getDescription : function() { 22 + return 'Listener/' + this.getID(); 23 + }, 24 + 25 + writeMessage : function(message) { 26 + var serial = JSON.stringify(message); 27 + 28 + var length = Buffer.byteLength(serial, 'utf8'); 29 + length = length.toString(); 30 + while (length.length < 8) { 31 + length = '0' + length; 32 + } 33 + 34 + this._socket.write(length + serial); 35 + } 36 + 37 + } 38 + 39 + });
+57
support/aphlict/server/lib/AphlictListenerList.js
··· 1 + var JX = require('javelin').JX; 2 + JX.require('AphlictListener', __dirname); 3 + 4 + JX.install('AphlictListenerList', { 5 + construct : function() { 6 + this._listeners = {}; 7 + }, 8 + 9 + members : { 10 + _listeners : null, 11 + _nextID : 0, 12 + _activeListenerCount : 0, 13 + _totalListenerCount : 0, 14 + 15 + addListener : function(socket) { 16 + var listener = new JX.AphlictListener( 17 + this._generateNextID(), 18 + socket); 19 + 20 + this._listeners[listener.getID()] = listener; 21 + this._activeListenerCount++; 22 + this._totalListenerCount++; 23 + 24 + return listener; 25 + }, 26 + 27 + removeListener : function(listener) { 28 + var id = listener.getID(); 29 + if (id in this._listeners) { 30 + delete this._listeners[id]; 31 + this._activeListenerCount--; 32 + } 33 + }, 34 + 35 + getListeners : function() { 36 + return this._listeners; 37 + }, 38 + 39 + getActiveListenerCount : function() { 40 + return this._activeListenerCount; 41 + }, 42 + 43 + getTotalListenerCount : function() { 44 + return this._totalListenerCount; 45 + }, 46 + 47 + _generateNextID : function() { 48 + do { 49 + this._nextID = ((this._nextID + 1) % 1000000000000); 50 + } while (this._nextID in this._listeners); 51 + 52 + return this._nextID; 53 + } 54 + 55 + } 56 + 57 + });
+52
support/aphlict/server/lib/AphlictLog.js
··· 1 + var JX = require('javelin').JX; 2 + 3 + var fs = require('fs'); 4 + var util = require('util'); 5 + 6 + JX.install('AphlictLog', { 7 + construct : function() { 8 + this._writeToLogs = []; 9 + this._writeToConsoles = []; 10 + }, 11 + 12 + members : { 13 + _writeToConsoles : null, 14 + _writeToLogs : null, 15 + 16 + addLogfile : function(path) { 17 + var options = { 18 + flags: 'a', 19 + encoding: 'utf8', 20 + mode: 066 21 + }; 22 + 23 + var logfile = fs.createWriteSteam(path, options); 24 + 25 + this._writeToLogs.push(logfile); 26 + 27 + return this; 28 + }, 29 + 30 + addConsole : function(console) { 31 + this._writeToConsoles.push(console); 32 + return this; 33 + }, 34 + 35 + log : function(pattern) { 36 + var str = util.format.apply(null, arguments); 37 + var date = new Date().toLocaleString(); 38 + str = '[' + date + '] ' + str; 39 + 40 + var ii; 41 + for (ii = 0; ii < this._writeToConsoles.length; ii++) { 42 + this._writeToConsoles[ii].log(str); 43 + } 44 + 45 + for (ii = 0; ii < this._writeToLogs.length; ii++) { 46 + this._writeToLogs[ii].write(str + "\n"); 47 + } 48 + } 49 + 50 + } 51 + 52 + });
+20 -4
webroot/rsrc/externals/javelin/core/init_node.js
··· 27 27 relative = relative || __dirname + '/..'; 28 28 var path = relative + '/' + thing + '.js'; 29 29 var content = fs.readFileSync(path); 30 + var dir = pathModule.dirname(path); 30 31 31 - var sandbox = { 32 + var k; 33 + var sandbox = {}; 34 + 35 + for (k in global) { 36 + sandbox[k] = global[k]; 37 + } 38 + 39 + var extra = { 32 40 JX : this, 33 41 __DEV__ : 0, 34 - console : console, 35 42 window : {}, 36 - require : function (thing) { 37 - return require(pathModule.dirname(path) + '/' + thing); 43 + __dirname : dir, 44 + require : function(thing) { 45 + if (thing == 'javelin') { 46 + return require(dir + '/' + thing); 47 + } else { 48 + return require(thing); 49 + } 38 50 } 39 51 }; 52 + 53 + for (k in extra) { 54 + sandbox[k] = extra[k]; 55 + } 40 56 41 57 vm.createScript(content, path) 42 58 .runInNewContext(sandbox, path);