UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

201 lines (169 loc) 7.83 kB
Object.defineProperty(exports, '__esModule', { value: true }); var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _nuclideAnalytics2; function _nuclideAnalytics() { return _nuclideAnalytics2 = require('../../nuclide-analytics'); } var _atom2; function _atom() { return _atom2 = require('atom'); } var _nuclideServerLibNuclideSocket2; function _nuclideServerLibNuclideSocket() { return _nuclideServerLibNuclideSocket2 = require('../../nuclide-server/lib/NuclideSocket'); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../nuclide-logging'); } var logger = (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)(); var HEARTBEAT_AWAY_REPORT_COUNT = 3; var HEARTBEAT_NOTIFICATION_ERROR = 1; var HEARTBEAT_NOTIFICATION_WARNING = 2; // Provides feedback to the user of the health of a NuclideSocket. var ConnectionHealthNotifier = (function () { function ConnectionHealthNotifier(host, socket) { var _this = this; _classCallCheck(this, ConnectionHealthNotifier); this._heartbeatNetworkAwayCount = 0; this._lastHeartbeatNotification = null; var serverUri = socket.getServerUri(); /** * Adds an Atom notification for the detected heartbeat network status * The function makes sure not to add many notifications for the same event and prioritize * new events. */ var addHeartbeatNotification = function addHeartbeatNotification(type, errorCode, message, dismissable, askToReload) { var _ref = _this._lastHeartbeatNotification || {}; var code = _ref.code; var existingNotification = _ref.notification; if (code && code === errorCode && dismissable) { // A dismissible heartbeat notification with this code is already active. return; } var notification = null; var options = { dismissable: dismissable, buttons: [] }; if (askToReload) { options.buttons.push({ className: 'icon icon-zap', onDidClick: function onDidClick() { atom.reload(); }, text: 'Reload Atom' }); } switch (type) { case HEARTBEAT_NOTIFICATION_ERROR: notification = atom.notifications.addError(message, options); break; case HEARTBEAT_NOTIFICATION_WARNING: notification = atom.notifications.addWarning(message, options); break; default: throw new Error('Unrecongnized heartbeat notification type'); } if (existingNotification) { existingNotification.dismiss(); } (0, (_assert2 || _assert()).default)(notification); _this._lastHeartbeatNotification = { notification: notification, code: errorCode }; }; var onHeartbeat = function onHeartbeat() { if (_this._lastHeartbeatNotification) { // If there has been existing heartbeat error/warning, // that means connection has been lost and we shall show a message about connection // being restored without a reconnect prompt. var _notification = _this._lastHeartbeatNotification.notification; _notification.dismiss(); atom.notifications.addSuccess('Connection restored to Nuclide Server at: ' + serverUri); _this._heartbeatNetworkAwayCount = 0; _this._lastHeartbeatNotification = null; } }; var notifyNetworkAway = function notifyNetworkAway(code) { _this._heartbeatNetworkAwayCount++; if (_this._heartbeatNetworkAwayCount >= HEARTBEAT_AWAY_REPORT_COUNT) { addHeartbeatNotification(HEARTBEAT_NOTIFICATION_WARNING, code, 'Nuclide server cannot be reached at "' + serverUri + '".<br/>' + 'Nuclide will reconnect when the network is restored.', /* dismissable */true, /* askToReload */false); } }; var onHeartbeatError = function onHeartbeatError(error) { var code = error.code; var message = error.message; var originalCode = error.originalCode; (0, (_nuclideAnalytics2 || _nuclideAnalytics()).trackEvent)({ type: 'heartbeat-error', data: { code: code || '', message: message || '', host: host } }); logger.info('Heartbeat network error:', code, originalCode, message); switch (code) { case 'NETWORK_AWAY': // Notify switching networks, disconnected, timeout, unreachable server or fragile // connection. notifyNetworkAway(code); break; case 'SERVER_CRASHED': // Server shut down or port no longer accessible. // Notify the server was there, but now gone. addHeartbeatNotification(HEARTBEAT_NOTIFICATION_ERROR, code, '**Nuclide Server Crashed**<br/>' + 'Please reload Atom to restore your remote project connection.', /* dismissable */true, /* askToReload */true); // TODO(most) reconnect ServerConnection, restore the current project state, // and finally change dismissable to false and type to 'WARNING'. break; case 'PORT_NOT_ACCESSIBLE': // Notify never heard a heartbeat from the server. var port = socket.getServerPort(); addHeartbeatNotification(HEARTBEAT_NOTIFICATION_ERROR, code, '**Nuclide Server Is Not Reachable**<br/>' + ('It could be running on a port that is not accessible: ' + String(port) + '.'), /* dismissable */true, /* askToReload */false); break; case 'INVALID_CERTIFICATE': // Notify the client certificate is not accepted by nuclide server // (certificate mismatch). addHeartbeatNotification(HEARTBEAT_NOTIFICATION_ERROR, code, '**Connection Reset Error**<br/>' + 'This could be caused by the client certificate mismatching the ' + 'server certificate.<br/>' + 'Please reload Atom to restore your remote project connection.', /* dismissable */true, /* askToReload */true); // TODO(most): reconnect ServerConnection, restore the current project state. // and finally change dismissable to false and type to 'WARNING'. break; default: notifyNetworkAway(code); logger.error('Unrecongnized heartbeat error code: ' + code, message); break; } }; this._subscription = new (_atom2 || _atom()).CompositeDisposable(socket.onHeartbeat(onHeartbeat), socket.onHeartbeatError(onHeartbeatError)); } _createClass(ConnectionHealthNotifier, [{ key: 'dispose', value: function dispose() { this._subscription.dispose(); } }]); return ConnectionHealthNotifier; })(); exports.ConnectionHealthNotifier = ConnectionHealthNotifier;