jenkins-bot has submitted this change and it was merged.

Change subject: Improve apiServer.js to support multiple mock and Parsoid 
servers
......................................................................


Improve apiServer.js to support multiple mock and Parsoid servers

Instead of just managing a single server, keep a map of them so
that multiple servers can be started from a single process. This
is necessary, for example, to test the Parsoid API using a mock MW
server.

Change-Id: I19f8dd106dc32095c07ce38e8c02eaf1f60d8ee4
---
M api/server.js
M tests/apiServer.js
M tests/mockAPI.js
3 files changed, 69 insertions(+), 29 deletions(-)

Approvals:
  Subramanya Sastry: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/api/server.js b/api/server.js
index ae98aab..f28a9b0 100755
--- a/api/server.js
+++ b/api/server.js
@@ -156,10 +156,13 @@
 } else {
        // Worker
 
-       process.on('SIGTERM', function() {
+       var shutdown_worker = function () {
                logger.log( "warning", "shutting down" );
                process.exit(0);
-       });
+       };
+
+       process.on('SIGTERM', shutdown_worker);
+       process.on('disconnect', shutdown_worker);
 
        // Enable heap dumps in /tmp on kill -USR2.
        // See https://github.com/bnoordhuis/node-heapdump/
diff --git a/tests/apiServer.js b/tests/apiServer.js
index acdd5e1..39fd84c 100644
--- a/tests/apiServer.js
+++ b/tests/apiServer.js
@@ -6,22 +6,40 @@
  * Uses port randomization to make sure we can use multiple servers 
concurrently.
  */
 
+require('es6-shim');
+
 var child_process = require( 'child_process' ),
        Util = require('../lib/mediawiki.Util.js').Util,
        path = require( 'path' );
 
-var forkedServer;
-var forkedServerURL;
+// Keep all started servers in a map indexed by the url
+var forkedServers = new Map(),
+       exiting = false;
 
-var stopServer = function () {
-       if ( forkedServer ) {
-               forkedServer.kill();
+var stopServer = function (url) {
+       var forkedServer = forkedServers.get(url);
+       if (forkedServer) {
+               // Prevent restart if we explicitly stop it
+               forkedServer.child.removeAllListeners('exit');
+               forkedServer.child.kill();
+               forkedServers.delete(url);
        }
 };
 
+var stopAllServers = function () {
+       forkedServers.forEach(function (forkedServer, url) {
+               stopServer(url);
+       });
+};
+
 /**
- * Make sure the server is killed if the process exits.
+ * Make sure the servers are killed if the process exits.
  */
+process.on('exit', function() {
+               exiting = true;
+               stopAllServers();
+});
+
 var exitOnProcessTerm = function (res) {
        var stopAndExit = function () {
                process.exit(res || 0);
@@ -38,23 +56,30 @@
  * Starts a server on passed port or a random port if none passed.
  * The callback will get the URL of the started server.
  */
-var startServer = function ( opts, cb, port ) {
+var startServer = function ( opts, cb, retrying ) {
+       var url, forkedServer = {}, port;
        if (!opts) {
                throw "Please provide server options.";
        }
+       forkedServer.opts = opts;
+       port = opts.port;
 
        // For now, we always assume that retries are due to port conflicts
-       if (!port || opts.retrying) {
+       if (!port) {
                port = opts.portBase + Math.floor( Math.random() * 100 );
        }
 
-       forkedServerURL = 'http://' + opts.iface + ':' + port.toString() + 
opts.urlPath;
-
-       if (!opts.quiet) {
-               console.log( "Starting " + opts.serverName + " server at", 
forkedServerURL );
+       url = 'http://' + opts.iface + ':' + port.toString() + opts.urlPath;
+       if (opts.port && forkedServers.has(url)) {
+               // We already have a server there!
+               throw "There's already a server running at that port.";
        }
 
-       forkedServer = child_process.fork(__dirname + opts.filePath,
+       if (!opts.quiet) {
+               console.log( "Starting %s server at %s", opts.serverName, url );
+       }
+
+       forkedServer.child = child_process.fork(__dirname + opts.filePath,
                opts.serverArgv,
                {
                        env: {
@@ -65,18 +90,21 @@
                }
        );
 
-       // If it dies on its own, restart it
-       forkedServer.on( 'exit', function( ) {
-               console.warn('apiServer quit; retry with a different port');
-               forkedServer = null;
-               opts.retrying = true;
-               startServer(opts, cb);
-       } );
+       forkedServers.set(url, forkedServer);
 
-       if (!opts.retrying) {
-               // If this process dies, kill our server
-               process.on( 'exit', stopServer );
+       // If it dies on its own, restart it. The most common cause will be 
that the
+       // port was already in use, so if no port was specified then a new 
random
+       // one will be selected.
+       forkedServer.child.on('exit', function (exitUrl) {
+               if (exiting) {
+                       return;
+               }
+               console.warn('Restarting server at', exitUrl);
+               forkedServers.delete(exitUrl);
+               startServer(opts, cb, true);
+       }.bind(null, url));
 
+       if (!retrying) {
                // HACK HACK HACK!!
                //
                // It is possible that we get into this callback in the time
@@ -91,8 +119,8 @@
                // the server url. But, that is more work and it is unclear
                // if we need it.
                var waitAndCB = function() {
-                       if (forkedServer) {
-                               cb(forkedServerURL, forkedServer);
+                       if (forkedServer.child) {
+                               cb(url, forkedServer.child);
                        } else {
                                setTimeout(waitAndCB, 2000);
                        }
@@ -118,7 +146,7 @@
 
 var startParsoidServer = function (opts, cb) {
        opts = !opts ? parsoidServerOpts : Util.extendProps(opts, 
parsoidServerOpts);
-       startServer(opts, cb, opts.port);
+       startServer(opts, cb);
 };
 
 var mockAPIServerOpts = {
@@ -133,12 +161,13 @@
 
 var startMockAPIServer = function (opts, cb) {
        opts = !opts ? mockAPIServerOpts : Util.extendProps(opts, 
mockAPIServerOpts);
-       startServer(opts, cb, opts.port);
+       startServer(opts, cb);
 };
 
 module.exports = {
        startServer: startServer,
        stopServer: stopServer,
+       stopAllServers: stopAllServers,
        startParsoidServer: startParsoidServer,
        startMockAPIServer: startMockAPIServer,
        exitOnProcessTerm: exitOnProcessTerm
diff --git a/tests/mockAPI.js b/tests/mockAPI.js
index eeab255..f405063 100644
--- a/tests/mockAPI.js
+++ b/tests/mockAPI.js
@@ -94,7 +94,15 @@
                        cb( null, { parse: { text: { '*': resultText } } } );
                },
 
+               querySiteinfo: function( body, cb ) {
+                       // TODO: Read which language should we use from 
somewhere.
+                       cb( null, require('../lib/baseconfig/enwiki.json') );
+               },
+
                query: function ( body, cb ) {
+                       if (body.meta === 'siteinfo') {
+                               return this.querySiteinfo( body, cb );
+                       }
                        var filename = body.titles,
                                normPagename = pnames[filename] || filename,
                                normFilename = fnames[filename] || filename;

-- 
To view, visit https://gerrit.wikimedia.org/r/172752
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I19f8dd106dc32095c07ce38e8c02eaf1f60d8ee4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: Marcoil <[email protected]>
Gerrit-Reviewer: Arlolra <[email protected]>
Gerrit-Reviewer: Cscott <[email protected]>
Gerrit-Reviewer: Subramanya Sastry <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to