UNPKG

webgme-engine

Version:

WebGME server and Client API without a GUI

365 lines (302 loc) 16 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: addon/addonmanager.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: addon/addonmanager.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/*globals requireJS*/ /*eslint-env node*/ /** * * @author pmeijer / https://github.com/pmeijer */ 'use strict'; var Q = require('q'), superagent = require('superagent'), BranchMonitor = require('./branchmonitor'), EventDispatcher = requireJS('common/EventDispatcher'), STORAGE_CONSTANTS = requireJS('common/storage/constants'), Storage = requireJS('common/storage/nodestorage'); /** * Class for managing branch-monitors within a single project. * Branch-monitors are managing the add-ons within each branch. * @param {string} projectId * @param {object} mainLogger * @param {object} gmeConfig * @param {number} gmeConfig.addOn.monitorTimeout - Time to wait before stopping a monitor after only the monitor itself * is connected to the branch. * @param {object} [options] * @param {object} [options.webgmeUrl=http://127.0.0.1:gmeConfig.server.port] * @constructor * @ignore */ function AddOnManager(projectId, mainLogger, gmeConfig, options) { var self = this, logger = mainLogger.fork('AddOnManager:' + projectId), webgmeUrl, initDeferred, closeDeferred; options = options || {}; webgmeUrl = options.webgmeUrl || 'http://127.0.0.1:' + gmeConfig.server.port; EventDispatcher.call(self); this.branchMonitors = { //branchName: { // instance: {BranchMonitor}, // lastActivity: Date.now(), // stopTimeout: { // id: {number}, // deferred: {Promise} // } }; this.project = null; this.storage = null; this.initRequested = false; this.closeRequested = false; this.webgmeToken = null; this.renewingToken = false; this.inStoppedAndStarted = 0; function removeMonitor(branchName) { var remainingMonitors; delete self.branchMonitors[branchName]; remainingMonitors = Object.keys(self.branchMonitors); logger.debug('Removing monitor [' + branchName + '] - remaining', remainingMonitors); if (remainingMonitors.length === 0 &amp;&amp; self.inStoppedAndStarted === 0) { self.dispatchEvent('NO_MONITORS'); } } /** * Opens up the storage based on the webgmeToken and opens and sets the project. * * @param {string} webgmeToken * @param {function} [callback] * @returns {Promise} */ this.initialize = function (webgmeToken, callback) { if (self.initRequested === false) { initDeferred = Q.defer(); self.initRequested = true; self.webgmeToken = webgmeToken; self.storage = Storage.createStorage(webgmeUrl, self.webgmeToken, logger, gmeConfig); self.storage.open(function (networkStatus) { if (networkStatus === STORAGE_CONSTANTS.CONNECTED) { self.storage.openProject(projectId, function (err, project, branches, rights) { if (err) { self.close() .finally(function () { initDeferred.reject(err); }); return; } self.project = project; if (rights.write === false) { logger.warn('AddOnManager for project [' + projectId + '] initialized without write access.'); } self.initialized = true; initDeferred.resolve(); }); self.storage.webSocket.addEventListener(STORAGE_CONSTANTS.NOTIFICATION, function (emitter, eventData) { logger.debug('received notification', eventData); if (eventData.type === STORAGE_CONSTANTS.BRANCH_ROOM_SOCKETS) { // If a new socket joined our branch -> emit to the branch room letting // any newly connected users know that we are in this branch too. self.storage.sendNotification({ state: null, // No client state in the addOns type: STORAGE_CONSTANTS.CLIENT_STATE_NOTIFICATION, projectId: projectId, branchName: eventData.branchName }, function (err) { if (err) { logger.error('Sending state notification failed', err); } }); } else { logger.debug('Unused notification', eventData.type); } } ); } else if (networkStatus === STORAGE_CONSTANTS.JWT_ABOUT_TO_EXPIRE) { if (!self.renewingToken) { self.renewingToken = true; superagent.get(webgmeUrl + '/api/user/token') .set('Authorization', 'Bearer ' + self.webgmeToken) .end(function (err, res) { self.renewingToken = false; if (err) { logger.error(err); } else { self.setToken(res.body.webgmeToken); } }); } } else if (networkStatus === STORAGE_CONSTANTS.DISCONNECTED) { logger.warn('Lost connection to storage, awaiting reconnect...'); } else if (networkStatus === STORAGE_CONSTANTS.RECONNECTED) { logger.info('Storage reconnected!'); } else { logger.error('Connection problems' + networkStatus); self.storage.close(function (err) { if (err) { logger.error(err); } initDeferred.reject(new Error('Problems connecting to the webgme server, network status: ' + networkStatus)); }); } }); } return initDeferred.promise.nodeify(callback); }; this.monitorBranch = function (branchName, callback) { var monitor = self.branchMonitors[branchName]; function startNewTimer() { return setTimeout(function () { var timedDeferred = monitor.stopTimeout.deferred; monitor.stopTimeout = null; monitor.instance.stop() .then(function () { removeMonitor(branchName); timedDeferred.resolve(); }) .catch(timedDeferred.reject); }, gmeConfig.addOn.monitorTimeout); } function startNewMonitor() { monitor = { lastActivity: Date.now(), stopTimeout: null, instance: new BranchMonitor( self.webgmeToken, self.storage, self.project, branchName, logger, gmeConfig, options) }; self.branchMonitors[branchName] = monitor; monitor.stopTimeout = { deferred: Q.defer(), id: startNewTimer(branchName) }; logger.debug('monitorBranch [' + branchName + '] - starting new monitor'); return monitor.instance.start(); } if (monitor) { if (monitor.stopTimeout) { // The monitor has been created and the stop hasn't been triggered, // so clear the old timeout and set a new one. clearTimeout(monitor.stopTimeout.id); monitor.stopTimeout.id = startNewTimer(branchName); monitor.lastActivity = Date.now(); return monitor.instance.start() .nodeify(callback); } else { // The timeout has been triggered, and the monitor is in stopping stage. // We cannot simply remove the monitor before it has closed the branch, // therefore we need to register on the stop.promise and start a new monitor // (or use an earlier added one) once it has resolved. // The counter ensures that this manager isn't destroyed. self.inStoppedAndStarted += 1; return monitor.instance.stop() .then(function () { self.inStoppedAndStarted -= 1; if (self.branchMonitors[branchName]) { return self.branchMonitors[branchName].instance.start(); } else { return startNewMonitor(); } }) .nodeify(callback); } } else { return startNewMonitor() .nodeify(callback); } }; this.unMonitorBranch = function (branchName, callback) { var deferred = Q.defer(); deferred.resolve({}); return deferred.promise.nodeify(callback); }; this.queryAddOn = function (webgmeToken, branchName, addOnId, queryParams, callback) { var deferred = Q.defer(); deferred.reject(new Error('Not Implemented!')); return deferred.promise.nodeify(callback); }; this.close = function (callback) { function stopMonitor(branchName) { clearTimeout(self.branchMonitors[branchName].stopTimeout.id); return self.branchMonitors[branchName].instance.stop(); } if (self.closeRequested === false) { closeDeferred = Q.defer(); self.closeRequested = true; Q.allSettled(Object.keys(self.branchMonitors).map(stopMonitor)) .then(function (/*results*/) { //TODO: Check the results and at least log errors. return Q.ninvoke(self.storage, 'close'); }) .then(function () { closeDeferred.resolve(); }) .catch(closeDeferred.reject); } return closeDeferred.promise.nodeify(callback); }; this.setToken = function (token) { self.webgmeToken = token; logger.debug('Setting new token..'); if (self.storage) { self.storage.setToken(token); } Object.keys(self.branchMonitors).forEach(function (branchName) { self.branchMonitors[branchName].instance.setToken(token); }); }; this.getStatus = function (/*opts*/) { var status = { initRequested: self.initRequested, closeRequested: self.closeRequested, renewingToken: self.renewingToken, inStoppedAndStarted: self.inStoppedAndStarted, branchMonitors: {} }; Object.keys(self.branchMonitors).forEach(function (branchName) { status.branchMonitors[branchName] = self.branchMonitors[branchName].instance.getStatus(); status.branchMonitors[branchName].lastActivity = self.branchMonitors[branchName].lastActivity; }); return status; }; } // Inherit from the EventDispatcher AddOnManager.prototype = Object.create(EventDispatcher.prototype); AddOnManager.prototype.constructor = AddOnManager; module.exports = AddOnManager;</code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="Server_GMEAuth.html">Server:GMEAuth</a></li><li><a href="Server_SafeStorage.html">Server:SafeStorage</a></li><li><a href="Server_UserProject.html">Server:UserProject</a></li><li><a href="module-Core.html">Core</a></li><li><a href="module-Storage.html">Storage</a></li><li><a href="module-crosscuts.html">crosscuts</a></li><li><a href="module-serialization.html">serialization</a></li></ul><h3>Externals</h3><ul><li><a href="external-Promise.html">Promise</a></li></ul><h3>Classes</h3><ul><li><a href="AddOnBase.html">AddOnBase</a></li><li><a href="AddOnUpdateResult.html">AddOnUpdateResult</a></li><li><a href="Artifact.html">Artifact</a></li><li><a href="BlobClient.html">BlobClient</a></li><li><a href="BlobMetadata.html">BlobMetadata</a></li><li><a href="BlobRunPluginClient.html">BlobRunPluginClient</a></li><li><a href="Client.html">Client</a></li><li><a href="Core.html">Core</a></li><li><a href="ExecutorClient.html">ExecutorClient</a></li><li><a href="GMENode.html">GMENode</a></li><li><a href="GmeLogger.html">GmeLogger</a></li><li><a href="InterPluginResult.html">InterPluginResult</a></li><li><a href="JobInfo.html">JobInfo</a></li><li><a href="OutputInfo.html">OutputInfo</a></li><li><a href="PluginBase.html">PluginBase</a></li><li><a href="PluginConfig.html">PluginConfig</a></li><li><a href="PluginMessage.html">PluginMessage</a></li><li><a href="PluginNodeDescription.html">PluginNodeDescription</a></li><li><a href="PluginResult.html">PluginResult</a></li><li><a href="Project.html">Project</a></li><li><a href="ProjectInterface.html">ProjectInterface</a></li><li><a href="Server_GMEAuth-GMEAuth.html">GMEAuth</a></li><li><a href="Server_SafeStorage-SafeStorage.html">SafeStorage</a></li><li><a href="Server_UserProject-UserProject.html">UserProject</a></li><li><a href="WebsocketRouter.html">WebsocketRouter</a></li><li><a href="WebsocketRouterUser.html">WebsocketRouterUser</a></li></ul><h3>Events</h3><ul><li><a href="Client.html#event:BRANCH_CHANGED">BRANCH_CHANGED</a></li><li><a href="Client.html#event:BRANCH_CLOSED">BRANCH_CLOSED</a></li><li><a href="Client.html#event:BRANCH_OPENED">BRANCH_OPENED</a></li><li><a href="Client.html#event:BRANCH_STATUS_CHANGED">BRANCH_STATUS_CHANGED</a></li><li><a href="Client.html#event:CONNECTED_USERS_CHANGED">CONNECTED_USERS_CHANGED</a></li><li><a href="Client.html#event:NETWORK_STATUS_CHANGED">NETWORK_STATUS_CHANGED</a></li><li><a href="Client.html#event:NOTIFICATION">NOTIFICATION</a></li><li><a href="Client.html#event:PLUGIN_FINISHED">PLUGIN_FINISHED</a></li><li><a href="Client.html#event:PLUGIN_INITIATED">PLUGIN_INITIATED</a></li><li><a href="Client.html#event:PLUGIN_NOTIFICATION">PLUGIN_NOTIFICATION</a></li><li><a href="Client.html#event:PROJECT_CLOSED">PROJECT_CLOSED</a></li><li><a href="Client.html#event:PROJECT_OPENED">PROJECT_OPENED</a></li></ul><h3><a href="global.html">Global</a></h3> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.2</a> on Fri Jun 21 2024 09:43:40 GMT-0400 (Eastern Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>