Beispiel #1
0
 action: function () {
   var data = {
     modified: now,
     runs: job.runs,
     runFailures: job.runFailures
   };
   if (!success) {
     data.failures = job.failures;
   }
   if (success) {
     // mark complete
     callback = job.success;
     data.status = 'complete';
     data.runs += 1;
   } else if (maxFailures === false || job.runFailures > maxFailures) {
     // mark failed
     callback = job.failure;
     data.status = 'failed';
     data.failures = job.failures;
   } else {
     data.delayUntil = now + getBackOffDelay(job, cfg);
     data.status = 'pending';
   }
   if (data.status !== 'pending' && data.runs < repeatTimes && now <= repeatUntil) {
     data.status = 'pending';
     data.delayUntil = now + repeatDelay;
     data.runFailures = 0;
   }
   db._jobs.update(job._key, data);
   job = _.extend(job, data);
 }
Beispiel #2
0
 db._listDatabases().forEach(function (name) {
   try {
     db._useDatabase(name);
     db._jobs.updateByExample({status: 'progress'}, {status: 'pending'});
     require('org/arangodb/foxx/queues')._updateQueueDelay();
   } catch(e) {}
 });
Beispiel #3
0
      .forEach(function (queue) {
        var numBusy = db._jobs.byExample({
          queue: queue._key,
          status: 'progress'
        }).count();

        if (numBusy >= queue.maxWorkers) {
          busy = true;
          return;
        }

        var jobs = db._createStatement({
          query: (
            qb.for('job').in('_jobs')
            .filter(
              qb('pending').eq('job.status')
              .and(qb.ref('@queue').eq('job.queue'))
              .and(qb.ref('@now').gte('job.delayUntil'))
            )
            .sort('job.delayUntil', 'ASC')
            .limit('@max')
            .return('job')
          ),
          bindVars: {
            queue: queue._key,
            now: Date.now(),
            max: queue.maxWorkers - numBusy
          }
        }).execute().toArray();

        if (jobs.length > 0) {
          busy = true;
        }

        jobs.forEach(function (job) {
          db._jobs.update(job._key, {status: 'progress'});
          tasks.register({
            command: function (cfg) {
              var db = require('org/arangodb').db;
              var initialDatabase = db._name();
              db._useDatabase(cfg.db);
              try {
                require('org/arangodb/foxx/queues/worker').work(cfg.job);
              } catch(e) {}
              db._useDatabase(initialDatabase);
            },
            offset: 1,
            isSystem: true,
            params: {
              job: _.extend({}, job, {status: 'progress'}),
              db: db._name()
            }
          });
        });
      });
Beispiel #4
0
 jobs.forEach(function (job) {
   db._jobs.update(job._key, {status: 'progress'});
   tasks.register({
     command: function (cfg) {
       var db = require('org/arangodb').db;
       var initialDatabase = db._name();
       db._useDatabase(cfg.db);
       try {
         require('org/arangodb/foxx/queues/worker').work(cfg.job);
       } catch(e) {}
       db._useDatabase(initialDatabase);
     },
     offset: 1,
     isSystem: true,
     params: {
       job: _.extend({}, job, {status: 'progress'}),
       db: db._name()
     }
   });
 });
Beispiel #5
0
exports.work = function (job) {
  var databaseName = db._name();
  var cache = queues._jobTypes[databaseName];
  var cfg = typeof job.type === 'string' ? (cache && cache[job.type]) : job.type;

  if (!cfg) {
    console.warn('Unknown job type for job %s in %s: %s', job._key, db._name(), job.type);
    db._jobs.update(job._key, {status: 'pending'});
    return;
  }

  var maxFailures = (
    typeof job.maxFailures === 'number' || job.maxFailures === false
    ? job.maxFailures
    : (
      typeof cfg.maxFailures === 'number' || cfg.maxFailures === false
      ? cfg.maxFailures
      : 0
    )
  );

  if (!job.runFailures) {
    job.runFailures = 0;
  }

  if (!job.runs) {
    job.runs = 0;
  }

  var repeatDelay = job.repeatDelay || cfg.repeatDelay || 0;
  var repeatTimes = job.repeatTimes || cfg.repeatTimes || 0;
  var repeatUntil = job.repeatUntil || cfg.repeatUntil || -1;
  var now = Date.now();
  var success = true;
  var result;

  if (repeatTimes < 0) {
    repeatTimes = Infinity;
  }

  if (repeatUntil < 0) {
    repeatUntil = Infinity;
  }

  try {
    if (cfg.execute) {
      result = cfg.execute(job.data, job._id);
    } else {
      fm.runScript(cfg.name, cfg.mount, [].concat(job.data, job._id));
    }
  } catch (e) {
    console.errorLines('Job %s failed:\n%s', job._key, e.stack || String(e));
    job.runFailures += 1;
    job.failures.push(flatten(e));
    success = false;
  }

  var callback;
  db._executeTransaction({
    collections: {
      read: ['_jobs'],
      write: ['_jobs']
    },
    action: function () {
      var data = {
        modified: now,
        runs: job.runs,
        runFailures: job.runFailures
      };
      if (!success) {
        data.failures = job.failures;
      }
      if (success) {
        // mark complete
        callback = job.success;
        data.status = 'complete';
        data.runs += 1;
      } else if (maxFailures === false || job.runFailures > maxFailures) {
        // mark failed
        callback = job.failure;
        data.status = 'failed';
        data.failures = job.failures;
      } else {
        data.delayUntil = now + getBackOffDelay(job, cfg);
        data.status = 'pending';
      }
      if (data.status !== 'pending' && data.runs < repeatTimes && now <= repeatUntil) {
        data.status = 'pending';
        data.delayUntil = now + repeatDelay;
        data.runFailures = 0;
      }
      db._jobs.update(job._key, data);
      job = _.extend(job, data);
    }
  });

  if (job.status === 'pending') {
    queues._updateQueueDelay();
  }

  if (callback) {
    var cbType = success ? 'success' : 'failure';
    try {
      var filename = util.format(
        '<foxx queue %s callback for job %s in %s>',
        cbType,
        job._key,
        db._name()
      );
      var fn = internal.executeScript('(' + callback + ')', undefined, filename);
      fn(job._id, job.data, result, job.failures);
    } catch (e) {
      console.errorLines(
        'Failed to execute %s callback for job %s in %s:\n%s',
        cbType,
        job._key,
        db._name(),
        e.stack || String(e)
      );
    }
  }
};