Skip to content

Commit

Permalink
Merge pull request #139 from joscha/patch-2
Browse files Browse the repository at this point in the history
fix: do not terminate random sessions
  • Loading branch information
lgandecki authored Jun 11, 2019
2 parents 130a0ea + 3447313 commit 32fcab0
Showing 1 changed file with 90 additions and 43 deletions.
133 changes: 90 additions & 43 deletions src/lib/saucelabs-manager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var request = require('request'),
log = require('./log');
log = require('./log'),
_ = require('underscore');

/**
* SessionManager Constructor
Expand All @@ -21,6 +22,8 @@ function SauceLabsSessionManager(options) {
this.retryDelay = 3000;
this.retry = 0;

this.build = null;

log.debug('[chimp][saucelabs-session-manager] created a new SessionManager', options);

}
Expand All @@ -39,17 +42,25 @@ SauceLabsSessionManager.prototype.remote = function (webdriverOptions, callback)
log.debug('[chimp][saucelabs-session-manager] creating webdriver remote ');
var browser = this.webdriver.remote(webdriverOptions);

this.build = webdriverOptions.desiredCapabilities.build;
log.debug('[chimp][saucelabs-session-manager] build: ' + this.build);

callback(null, browser);
return;
};

var DEFAULT_LIMIT = 100;

/**
* Gets a list of sessions from the SauceLabs API based on Build ID
*
* @api private
*/
SauceLabsSessionManager.prototype._getJobs = function (callback) {
var hub = this.options.sauceLabsUrl + '/jobs?full=:get_full_info&limit=10'; //default is 100 which seems like too much
SauceLabsSessionManager.prototype._getJobs = function (callback, limit, skip) {
var hub = this.options.sauceLabsUrl + '/jobs?full=true&limit=' + limit;
if (skip > 0) {
hub += '&skip=' + skip;
}

log.debug('[chimp][saucelabs-session-manager]', 'requesting sessions from', hub);

Expand All @@ -65,53 +76,89 @@ SauceLabsSessionManager.prototype._getJobs = function (callback) {
};

/**
* Kills the 1st session found running on SauceLabs
*
* @api public
*/
SauceLabsSessionManager.prototype.killCurrentSession = function (callback) {

this._getJobs(function (err, jobs) {
if (jobs && jobs.length) {
var job = jobs[0];

// This will stop the session, causing a 'User terminated' error.
// If we don't manually stop the session, we get a timed-out error.
var options = {
url: this.options.sauceLabsUrl + '/jobs/' + job.id + '/stop',
method: 'PUT'
};

request(options, function (error, response) {
if (!error && response.statusCode === 200) {
log.debug('[chimp][saucelabs-session-manager]', 'stopped session');
callback();
} else {
log.error('[chimp][saucelabs-session-manager]', 'received error', error);
callback(error);
var self = this;
var killSession = function (job) {
// This will stop the session, causing a 'User terminated' error.
// If we don't manually stop the session, we get a timed-out error.
var options = {
url: this.options.sauceLabsUrl + '/jobs/' + job.id + '/stop',
method: 'PUT'
};

request(options, function (error, response) {
if (!error && response.statusCode === 200) {
log.debug('[chimp][saucelabs-session-manager]', 'stopped session');
callback();
} else {
log.error('[chimp][saucelabs-session-manager]', 'received error', error);
callback(error);
}
});

// This will set the session to passing or else it will show as Errored out
// even though we stop it.
options = {
url: this.options.sauceLabsUrl + '/jobs/' + job.id,
method: 'PUT',
json: true,
body: { passed: true }
};

request(options, function (error, response) {
if (!error && response.statusCode === 200) {
log.debug('[chimp][saucelabs-session-manager]', 'updated session to passing state');
callback();
} else {
log.error('[chimp][saucelabs-session-manager]', 'received error', error);
callback(error);
}
});
}.bind(this)

var getJobForBuild = function(cb, skip) {
if (!self.build) {
// get one and kill it, this is the (flawed) default of chimp which will just randomly
// terminate sessions and you get an odd `Error: The test with session id XXX has already finished, and can't receive further commands.` error
console.warn('You should really consider setting a build, otherwise random sessions will be terminated!');
this._getJobs(function(err, jobs) {
if (jobs.length) {
killSession(jobs[0]);
}
}, 1);
return;
}
this._getJobs(function(err, jobs) {
// the original code never uses this error,
// probably because if we don't find anything we just leave the session alone
// we might want to revisit this behavior
// if (err) {
// cb(err);
// }
if (!jobs.length) {
// no more jobs found, let's exit
console.warn(`Couldn't find a job to terminate for build ${self.build}`);
callback();
return;
}
var currentJob = _.find(jobs, function (b) {
return b.build === self.build;
});
if (!currentJob) {
// maybe it's in the next batch?
getJobForBuild(cb, skip + DEFAULT_LIMIT)
} else {
killSession(currentJob);
}
}, DEFAULT_LIMIT, skip);
}.bind(this)

// This will set the session to passing or else it will show as Errored out
// even though we stop it.
options = {
url: this.options.sauceLabsUrl + '/jobs/' + job.id,
method: 'PUT',
json: true,
body: { passed: true }
};

request(options, function (error, response) {
if (!error && response.statusCode === 200) {
log.debug('[chimp][saucelabs-session-manager]', 'updated session to passing state');
callback();
} else {
log.error('[chimp][saucelabs-session-manager]', 'received error', error);
callback(error);
}
});
}
}.bind(this));


getJobForBuild(killSession, 0);
};

module.exports = SauceLabsSessionManager;

0 comments on commit 32fcab0

Please sign in to comment.