attester/attester

View on GitHub
lib/attester/server.js

Summary

Maintainability
A
1 hr
Test Coverage
/*
 * Copyright 2013 Amadeus s.a.s.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var Q = require('q');

var TestServer = require("../test-server/test-server.js");

var attester = require("../attester");
var config = attester.config;

/**
 * The server module is responsible of starting a test server which is then serving files to connected slaves and
 * gathering results.
 */
var testServer = null;
var testServerReady = false;

/**
 * @return {Promise}
 */

function closeServer() {
    if (!testServerReady) {
        logResetDone();
        return Q();
    }
    attester.logger.logDebug("Closing the server");
    testServerReady = false;

    if (testServer) {
        var deferred = Q.defer();
        // TODO make testServer.dispose return promise
        testServer.dispose(function () {
            testServer = null;
            deferred.resolve();
        });
        logResetDone();
        return deferred.promise;
    } else {
        logResetDone();
        return Q();
    }
}

function logResetDone() {
    attester.logger.logDebug("__reset__ server done");
}

exports.__init__ = function () {
    attester.event.on("attester.campaign.initialized", exports.addCampaign);
};

// It is enough to have a single server, it should be able to serve multiple campaigns
exports.create = function (callback) {
    testServer = new TestServer({
        predictableUrls: config["predictable-urls"],
        shutdownOnCampaignEnd: config["shutdown-on-campaign-end"],
        frozen: config["server-only"],
        flashPolicyPort: config["flash-policy-port"],
        flashPolicyServer: config["flash-policy-server"],
        taskTimeout: config["task-timeout"],
        maxTaskRestarts: config["max-task-restarts"],
        taskRestartOnFailure: config["task-restart-on-failure"],
        publicHost: config['public-host'],
        publicPort: config['public-port']
    }, attester.logger);

    testServer.server.on("error", function (error) {
        if (error.code === "EADDRINUSE") {
            // choose an arbitrary unused port:
            testServer.server.listen(0, config.host);
        } else {
            testServer.logger.logError("Web server error: %s", [error]);
            attester.event.emit("server.error");
        }
    });

    testServer.listen(config.port, config.host, function () {
        var port = testServer.port;
        if (port != config.port && config.port > 0) {
            // logging error instead of a warning so it's more visible in the console
            attester.logger.logError("Port %d unavailable; using %d instead.", [config.port, port]);
        }

        testServerReady = true;
        attester.event.emit("server.listening");
        callback();
    });
};

exports.addCampaign = function (campaign) {
    testServer.addCampaign(campaign);
};

exports.getRemainingTasks = function () {
    return testServer.getRemainingTasks();
};

/**
 * Add a given middleware to the one already served. This should normally be called by plugins that want to include
 * global middlewares to be served on any campaign
 */
exports.use = function (path, middleware) {
    if (!testServerReady) {
        attester.event.once("server.listening", addMiddleware.bind(this, path, middleware));
    } else {
        addMiddleware(path, middleware);
    }
};

function addMiddleware(path, middleware) {
    if (!middleware) {
        middleware = path;
        path = "/";
    }
    testServer.app.use(path, middleware);
}

exports.__reset__ = function () {
    attester.event.off("attester.campaign.initialized", exports.addCampaign);
    return closeServer();
};