PUT /files/util/job_queue.js HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: identity
Content-Length: 1690
Content-MD5: xvMeGokCFL5GKtNtp3z9nw==
Expect: 100-continue
Date: Thu, 08 Dec 2016 13:02:37 GMT
User-Agent: aws-cli/1.11.26 Python/2.7.10 Darwin/16.1.0 botocore/1.4.83
Content-Type: application/javascript
Authorization: AWS 123:utbVdCw4W/+osxQfeVKVCn0vXl0=

'use strict';

// var _ = require('lodash');
var P = require('./promise');
var LinkedList = require('./linked_list');

const DIRECTION_FIFO = 'FIFO';
const DIRECTION_LIFO = 'LIFO';

class JobQueue {

    constructor(params) {
        this._name = params && params.name || '';
        this._concurrency = params && params.concurrency || 0;
        this._job_method = params && params.job_method || 'run';
        this._direction = params && params.direction || DIRECTION_FIFO;
        this._queue = new LinkedList(this._name);
        this._num_running = 0;
        Object.defineProperty(this, 'length', {
            enumerable: true,
            get: function() {
                return this._queue.length;
            }
        });
    }

    // add the given job to the jobs queue
    // which will run it when time comes.
    // job have its method property (by default 'run').
    add(job) {
        if (this._direction === DIRECTION_LIFO) {
            this._queue.push_front(job);
        } else {
            this._queue.push_back(job);
        }
        this.process(true);
    }

    remove(job) {
        return this._queue.remove(job);
    }

    process(check_concurrency) {
        if (check_concurrency && this._num_running >= this._concurrency) return;
        var job = this._queue.pop_front();
        if (!job) return;
        // submit the job to run in background
        // to be able to return here immediately
        this._num_running++;
        return P.try(() => job[this._job_method]())
            .finally(() => {
                this._num_running--;
                setImmediate(() => this.process(true));
            });
    }
}


module.exports = JobQueue;
