diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,8 +7,8 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'f8f4b8dc', - 'core.pkg.js' => '65e04767', + 'core.pkg.css' => '86353aff', + 'core.pkg.js' => '23d653bb', 'darkconsole.pkg.js' => '8ab24e01', 'differential.pkg.css' => '380f07e5', 'differential.pkg.js' => '7b5a4aa4', @@ -124,9 +124,9 @@ 'rsrc/css/phui/phui-action-list.css' => '9ee9910a', 'rsrc/css/phui/phui-action-panel.css' => '4bcb288d', 'rsrc/css/phui/phui-box.css' => '7b3a2eed', - 'rsrc/css/phui/phui-button.css' => 'ffe12633', + 'rsrc/css/phui/phui-button.css' => '008ba5e2', 'rsrc/css/phui/phui-crumbs-view.css' => '594d719e', - 'rsrc/css/phui/phui-document.css' => '8240b0b1', + 'rsrc/css/phui/phui-document.css' => 'a494bdf8', 'rsrc/css/phui/phui-error-view.css' => 'ad042fdd', 'rsrc/css/phui/phui-feed-story.css' => 'c9f3a0b5', 'rsrc/css/phui/phui-fontkit.css' => '9ae12677', @@ -210,7 +210,7 @@ 'rsrc/externals/javelin/lib/Scrollbar.js' => '5b2f5a08', 'rsrc/externals/javelin/lib/URI.js' => '6eff08aa', 'rsrc/externals/javelin/lib/Vector.js' => '2caa8fb8', - 'rsrc/externals/javelin/lib/WebSocket.js' => '3f840822', + 'rsrc/externals/javelin/lib/WebSocket.js' => 'e292eaf4', 'rsrc/externals/javelin/lib/Workflow.js' => '84d6aea0', 'rsrc/externals/javelin/lib/__tests__/Cookie.js' => '5ed109e8', 'rsrc/externals/javelin/lib/__tests__/DOM.js' => 'c984504b', @@ -697,7 +697,7 @@ 'javelin-view-interpreter' => 'f829edb3', 'javelin-view-renderer' => '6c2b09a2', 'javelin-view-visitor' => 'efe49472', - 'javelin-websocket' => '3f840822', + 'javelin-websocket' => 'e292eaf4', 'javelin-workflow' => '84d6aea0', 'lightbox-attachment-css' => '7acac05d', 'maniphest-batch-editor' => '8f380ebc', @@ -773,13 +773,13 @@ 'phui-action-header-view-css' => '89c497e7', 'phui-action-panel-css' => '4bcb288d', 'phui-box-css' => '7b3a2eed', - 'phui-button-css' => 'ffe12633', + 'phui-button-css' => '008ba5e2', 'phui-calendar-css' => '8675968e', 'phui-calendar-day-css' => 'de035c8a', 'phui-calendar-list-css' => 'c1d0ca59', 'phui-calendar-month-css' => 'a92e47d2', 'phui-crumbs-view-css' => '594d719e', - 'phui-document-view-css' => '8240b0b1', + 'phui-document-view-css' => 'a494bdf8', 'phui-error-view-css' => 'ad042fdd', 'phui-feed-story-css' => 'c9f3a0b5', 'phui-font-icon-base-css' => '3dad2ae3', @@ -1064,9 +1064,6 @@ 'javelin-dom', 'phortune-credit-card-form', ), - '3f840822' => array( - 'javelin-install', - ), '40a6a403' => array( 'javelin-install', 'javelin-dom', @@ -1807,6 +1804,9 @@ 'javelin-stratcom', 'javelin-dom', ), + 'e292eaf4' => array( + 'javelin-install', + ), 'e32d14ab' => array( 'javelin-behavior', 'javelin-stratcom', diff --git a/src/applications/notification/client/PhabricatorNotificationClient.php b/src/applications/notification/client/PhabricatorNotificationClient.php --- a/src/applications/notification/client/PhabricatorNotificationClient.php +++ b/src/applications/notification/client/PhabricatorNotificationClient.php @@ -2,12 +2,13 @@ final class PhabricatorNotificationClient { - const EXPECT_VERSION = 6; + const EXPECT_VERSION = 7; public static function getServerStatus() { $uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); $uri = id(new PhutilURI($uri)) - ->setPath('/status/'); + ->setPath('/status/') + ->setQueryParam('instance', self::getInstance()); list($body) = id(new HTTPSFuture($uri)) ->setTimeout(3) @@ -40,7 +41,8 @@ private static function postMessage(array $data) { $server_uri = PhabricatorEnv::getEnvConfig('notification.server-uri'); $server_uri = id(new PhutilURI($server_uri)) - ->setPath('/'); + ->setPath('/') + ->setQueryParam('instance', self::getInstance()); id(new HTTPSFuture($server_uri, json_encode($data))) ->setMethod('POST') @@ -48,4 +50,9 @@ ->resolvex(); } + private static function getInstance() { + $client_uri = PhabricatorEnv::getEnvConfig('notification.client-uri'); + return id(new PhutilURI($client_uri))->getPath(); + } + } diff --git a/src/applications/notification/controller/PhabricatorNotificationStatusController.php b/src/applications/notification/controller/PhabricatorNotificationStatusController.php --- a/src/applications/notification/controller/PhabricatorNotificationStatusController.php +++ b/src/applications/notification/controller/PhabricatorNotificationStatusController.php @@ -44,6 +44,7 @@ $value = phutil_format_relative_time_detailed($value); break; case 'log': + case 'instance': break; default: $value = number_format($value); diff --git a/support/aphlict/server/lib/AphlictAdminServer.js b/support/aphlict/server/lib/AphlictAdminServer.js --- a/support/aphlict/server/lib/AphlictAdminServer.js +++ b/support/aphlict/server/lib/AphlictAdminServer.js @@ -5,6 +5,7 @@ require('./AphlictListenerList'); var http = require('http'); +var url = require('url'); JX.install('AphlictAdminServer', { @@ -25,12 +26,8 @@ _server: null, _startTime: null, - getListeners: function() { - return this.getListenerList().getListeners(); - }, - - getListenerList: function() { - return this.getClientServer().getListenerList(); + getListenerList: function(instance) { + return this.getClientServer().getListenerList(instance); }, listen: function() { @@ -39,9 +36,11 @@ _handler: function(request, response) { var self = this; + var u = url.parse(request.url, true); + var instance = u.query.instance || '/'; // Publishing a notification. - if (request.url == '/') { + if (u.pathname == '/') { if (request.method == 'POST') { var body = ''; @@ -54,11 +53,12 @@ var msg = JSON.parse(body); self.getLogger().log( - 'Received notification: ' + JSON.stringify(msg)); + 'Received notification (' + instance + '): ' + + JSON.stringify(msg)); ++self._messagesIn; try { - self._transmit(msg); + self._transmit(instance, msg); response.writeHead(200, {'Content-Type': 'text/plain'}); } catch (err) { self.getLogger().log( @@ -81,14 +81,17 @@ response.writeHead(405, 'Method Not Allowed'); response.end(); } - } else if (request.url == '/status/') { + } else if (u.pathname == '/status/') { var status = { + 'instance': instance, 'uptime': (new Date().getTime() - this._startTime), - 'clients.active': this.getListenerList().getActiveListenerCount(), - 'clients.total': this.getListenerList().getTotalListenerCount(), + 'clients.active': this.getListenerList(instance) + .getActiveListenerCount(), + 'clients.total': this.getListenerList(instance) + .getTotalListenerCount(), 'messages.in': this._messagesIn, 'messages.out': this._messagesOut, - 'version': 6 + 'version': 7 }; response.writeHead(200, {'Content-Type': 'application/json'}); @@ -103,10 +106,12 @@ /** * Transmits a message to all subscribed listeners. */ - _transmit: function(message) { - var listeners = this.getListeners().filter(function(client) { - return client.isSubscribedToAny(message.subscribers); - }); + _transmit: function(instance, message) { + var listeners = this.getListenerList(instance) + .getListeners() + .filter(function(client) { + return client.isSubscribedToAny(message.subscribers); + }); for (var i = 0; i < listeners.length; i++) { var listener = listeners[i]; @@ -119,7 +124,7 @@ '<%s> Wrote Message', listener.getDescription()); } catch (error) { - this.getListenerList().removeListener(listener); + this.getListenerList(instance).removeListener(listener); this.getLogger().log( '<%s> Write Error: %s', listener.getDescription(), diff --git a/support/aphlict/server/lib/AphlictClientServer.js b/support/aphlict/server/lib/AphlictClientServer.js --- a/support/aphlict/server/lib/AphlictClientServer.js +++ b/support/aphlict/server/lib/AphlictClientServer.js @@ -5,19 +5,28 @@ require('./AphlictListenerList'); require('./AphlictLog'); +var url = require('url'); var util = require('util'); var WebSocket = require('ws'); JX.install('AphlictClientServer', { construct: function(server) { - this.setListenerList(new JX.AphlictListenerList()); this.setLogger(new JX.AphlictLog()); this._server = server; + this._lists = {}; }, members: { _server: null, + _lists: null, + + getListenerList: function(path) { + if (!this._lists[path]) { + this._lists[path] = new JX.AphlictListenerList(path); + } + return this._lists[path]; + }, listen: function() { var self = this; @@ -25,7 +34,8 @@ var wss = new WebSocket.Server({server: server}); wss.on('connection', function(ws) { - var listener = self.getListenerList().addListener(ws); + var path = url.parse(ws.upgradeReq.url).pathname; + var listener = self.getListenerList(path).addListener(ws); function log() { self.getLogger().log( @@ -70,12 +80,12 @@ }); ws.on('close', function() { - self.getListenerList().removeListener(listener); + self.getListenerList(path).removeListener(listener); log('Disconnected.'); }); wss.on('close', function() { - self.getListenerList().removeListener(listener); + self.getListenerList(path).removeListener(listener); log('Disconnected.'); }); @@ -90,7 +100,6 @@ }, properties: { - listenerList: null, logger: null, } diff --git a/support/aphlict/server/lib/AphlictListener.js b/support/aphlict/server/lib/AphlictListener.js --- a/support/aphlict/server/lib/AphlictListener.js +++ b/support/aphlict/server/lib/AphlictListener.js @@ -3,15 +3,18 @@ var JX = require('./javelin').JX; JX.install('AphlictListener', { - construct: function(id, socket) { + construct: function(id, socket, path) { this._id = id; this._socket = socket; + this._path = path; + this._subscriptions = {}; }, members: { _id: null, _socket: null, - _subscriptions: {}, + _path: null, + _subscriptions: null, getID: function() { return this._id; @@ -47,7 +50,7 @@ }, getDescription: function() { - return 'Listener/' + this.getID(); + return 'Listener/' + this.getID() + this._path; }, writeMessage: function(message) { diff --git a/support/aphlict/server/lib/AphlictListenerList.js b/support/aphlict/server/lib/AphlictListenerList.js --- a/support/aphlict/server/lib/AphlictListenerList.js +++ b/support/aphlict/server/lib/AphlictListenerList.js @@ -5,17 +5,22 @@ require('./AphlictListener'); JX.install('AphlictListenerList', { - construct: function() { + construct: function(path) { + this._path = path; this._listeners = {}; }, members: { _listeners: null, + _path: null, _nextID: 0, _totalListenerCount: 0, addListener: function(socket) { - var listener = new JX.AphlictListener(this._generateNextID(), socket); + var listener = new JX.AphlictListener( + this._generateNextID(), + socket, + this._path); this._listeners[listener.getID()] = listener; this._totalListenerCount++; diff --git a/webroot/rsrc/externals/javelin/lib/WebSocket.js b/webroot/rsrc/externals/javelin/lib/WebSocket.js --- a/webroot/rsrc/externals/javelin/lib/WebSocket.js +++ b/webroot/rsrc/externals/javelin/lib/WebSocket.js @@ -11,6 +11,7 @@ construct: function(uri) { this.setURI(uri); + this._resetDelay(); }, properties: { @@ -70,7 +71,6 @@ } this._shouldClose = false; - this._resetDelay(); this._socket = new WebSocket(this.getURI()); this._socket.onopen = JX.bind(this, this._onopen); @@ -171,6 +171,9 @@ // connection, the close handler will send us back here. We'll reconnect // more and more slowly until we eventually get a valid connection. this._delayUntilReconnect = this._delayUntilReconnect * 2; + + // Max out at 5 minutes between attempts. + this._delayUntilReconnect = Math.min(this._delayUntilReconnect, 300000); this.open(); }