<commit_before>var PulsarExec = require('./exec');
var PulsarJob = require('./job');
var events = require('events');
var util = require('util');
var _ = require('underscore');
var async = require('async');
var shellwords = require('shellwords');
var getLog = require('../logger').getLog;

module.exports = (function() {

  /**
   * @param {Object} db
   * @param {Object} config
   * @constructor
   */
  var Pulsar = function(db, config) {
    this.db = db;
    this.config = config || {};
    this.jobQueue = {};
    this._isShuttingDown = false;

    events.EventEmitter.call(this);
    this._enableGracefulShutdown();
  };

  util.inherits(Pulsar, events.EventEmitter);

  Pulsar.ILLEGAL_TASKS = ['invoke', 'shell'];

  /**
   * @callback Pulsar~createJobCallback
   * @param {Error} error
   * @param {PulsarJob} job
   */
  /**
   * @param {String} app
   * @param {String} env
   * @param {String} task
   * @param {Object} [taskVariables]
   * @param {Pulsar~createJobCallback} callback
   */
  Pulsar.prototype.createJob = function(app, env, task, taskVariables, callback) {
    if (!task || !_.isString(task) || !task.trim()) {
      throw new ValidationError('create pulsar job requires a pulsar task');
    }
    task = task.trim();
    if (_.contains(Pulsar.ILLEGAL_TASKS, task)) {
      throw new ValidationError('Illegal pulsar task');
    }
    var args = {
      app: app,
      env: env,
      task: task
    };
    if (taskVariables) {
      if (_.isFunction(taskVariables)) {
        callback = taskVariables;
      } else {
        this._validateTaskVariables(taskVariables);
        args.capistranoOptions = this._taskVariablesToCapistrano(taskVariables);
      }
    }
    var job = this._createJob(args);
    this._saveJob(job, callback);
  };

  /**
   * @param {String} jobId
   * @param {PulsarDB~getJobCallback} callback
   */
  Pulsar.prototype.getJob = function(jobId, callback) {
    if (this.jobQueue[jobId]) {
      return callback(null, this.jobQueue[jobId]);
    }
    this.db.getJob(jobId, callback);
  };

  /**
   * @callback Pulsar~getAvailableTasks
   * @param {Error} error
   * @param {Object.<string, string>} jobs, where key is task name and value is task description.
   */
  /**
   * @param {String} app
   * @param {String} env
   * @param {Pulsar~getAvailableTasks} callback
   */
  Pulsar.prototype.getAvailableTasks = function(app, env, callback) {
    var args = {
      app: app,
      env: env,
      capistranoOptions: ['-v', '--tasks']
    };
    var job = this._createJob(args);
    job.on('close', function() {
      if (job.status != PulsarJob.STATUS.FINISHED) {
        return callback(new Error('Collecting of available tasks finished abnormally.\n' + job.output));
      }
      var regex = /cap\s([^\s]+)\s+#\s(.*)\n/g;
      var match;
      var jobs = {};
      while (null !== (match = regex.exec(job.stdout))) {
        jobs[match[1]] = match[2];
      }
      return callback(null, jobs);
    });
    job.execute();
  };

  /**
   * @see PulsarDB.getJobList
   */
  Pulsar.prototype.getJobList = function(callback, currentPage, pageSize) {
    return this.db.getJobList(callback, currentPage, pageSize);
  };

  /**
   * @returns {boolean}
   */
  Pulsar.prototype.isShuttingDown = function() {
    return this._isShuttingDown;
  };

  /**
   * @param {PulsarJob} job
   * @param {Function} callback
   */
  Pulsar.prototype.restartJob = function(job, callback) {
    if (_.contains([PulsarJob.STATUS.KILLED, PulsarJob.STATUS.FAILED], job.status)) {
      getLog().debug('Job restart', {id: job.id});
      job.createInitialData();
      this._saveJob(job, function(err) {
        if (!err) {
          job.execute();
        }
        callback(err, job);
      });
    }
  };

  /**
   * @param {Object} args {@see PulsarExec}
   * @param {Object} [data] {@see PulsarExec}<commit_msg>Throw error in case of invalid restart status.<commit_after>var PulsarExec = require('./exec');
var PulsarJob = require('./job');
var events = require('events');
var util = require('util');
var _ = require('underscore');
var async = require('async');
var shellwords = require('shellwords');
var getLog = require('../logger').getLog;

module.exports = (function() {

  /**
   * @param {Object} db
   * @param {Object} config
   * @constructor
   */
  var Pulsar = function(db, config) {
    this.db = db;
    this.config = config || {};
    this.jobQueue = {};
    this._isShuttingDown = false;

    events.EventEmitter.call(this);
    this._enableGracefulShutdown();
  };

  util.inherits(Pulsar, events.EventEmitter);

  Pulsar.ILLEGAL_TASKS = ['invoke', 'shell'];

  /**
   * @callback Pulsar~createJobCallback
   * @param {Error} error
   * @param {PulsarJob} job
   */
  /**
   * @param {String} app
   * @param {String} env
   * @param {String} task
   * @param {Object} [taskVariables]
   * @param {Pulsar~createJobCallback} callback
   */
  Pulsar.prototype.createJob = function(app, env, task, taskVariables, callback) {
    if (!task || !_.isString(task) || !task.trim()) {
      throw new ValidationError('create pulsar job requires a pulsar task');
    }
    task = task.trim();
    if (_.contains(Pulsar.ILLEGAL_TASKS, task)) {
      throw new ValidationError('Illegal pulsar task');
    }
    var args = {
      app: app,
      env: env,
      task: task
    };
    if (taskVariables) {
      if (_.isFunction(taskVariables)) {
        callback = taskVariables;
      } else {
        this._validateTaskVariables(taskVariables);
        args.capistranoOptions = this._taskVariablesToCapistrano(taskVariables);
      }
    }
    var job = this._createJob(args);
    this._saveJob(job, callback);
  };

  /**
   * @param {String} jobId
   * @param {PulsarDB~getJobCallback} callback
   */
  Pulsar.prototype.getJob = function(jobId, callback) {
    if (this.jobQueue[jobId]) {
      return callback(null, this.jobQueue[jobId]);
    }
    this.db.getJob(jobId, callback);
  };

  /**
   * @callback Pulsar~getAvailableTasks
   * @param {Error} error
   * @param {Object.<string, string>} jobs, where key is task name and value is task description.
   */
  /**
   * @param {String} app
   * @param {String} env
   * @param {Pulsar~getAvailableTasks} callback
   */
  Pulsar.prototype.getAvailableTasks = function(app, env, callback) {
    var args = {
      app: app,
      env: env,
      capistranoOptions: ['-v', '--tasks']
    };
    var job = this._createJob(args);
    job.on('close', function() {
      if (job.status != PulsarJob.STATUS.FINISHED) {
        return callback(new Error('Collecting of available tasks finished abnormally.\n' + job.output));
      }
      var regex = /cap\s([^\s]+)\s+#\s(.*)\n/g;
      var match;
      var jobs = {};
      while (null !== (match = regex.exec(job.stdout))) {
        jobs[match[1]] = match[2];
      }
      return callback(null, jobs);
    });
    job.execute();
  };

  /**
   * @see PulsarDB.getJobList
   */
  Pulsar.prototype.getJobList = function(callback, currentPage, pageSize) {
    return this.db.getJobList(callback, currentPage, pageSize);
  };

  /**
   * @returns {boolean}
   */
  Pulsar.prototype.isShuttingDown = function() {
    return this._isShuttingDown;
  };

  /**
   * @param {PulsarJob} job
   * @param {Function} callback
   */
  Pulsar.prototype.restartJob = function(job, callback) {
    if (_.contains([PulsarJob.STATUS.KILLED, PulsarJob.STATUS.FAILED], job.status)) {
      getLog().debug('Job restart', {id: job.id});
      job.createInitialData();
      this._saveJob(job, function(err) {
        if (!err) {
          job.execute();
        }
        callback(err, job);
      });
    } else {
      throw new PulsarError('You can restart only KILLED or FAILED jobs', 500);
    }
  };

  /**
   * @param {Object} args {@see PulsarExec}
   * @param {Object} [data] {@see PulsarExec}
{'fraction_non_alphanumeric': 0.1582375478927203, 'fraction_numerical': 0.0008939974457215837, 'mean_word_length': 2.8406081412457085, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6675865', 'n_tokens_mistral': 2623, 'n_tokens_neox': 2580, 'n_words': 552}