moysklad-extension-queue
Version:
Очередь http запросов (расширение для библиотеки moysklad)
147 lines (121 loc) • 5.12 kB
JavaScript
;
// const debug = require('debug')
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
const test = require('blue-tape');
const Queue = require('../queue');
const sleep = require('moysklad/tools/sleep');
test('Queue is ok', t => {
t.ok(Queue);
t.equals(typeof Queue, 'function');
t.end();
});
test('Queue instance', t => {
let queue = new Queue();
t.ok(queue, 'should be truthy');
t.equals(queue.period, 3100, 'should have `period` property default to 5200');
t.equals(queue.tasksPerPeriod, 44, 'should have `tasksPerPeriod` property default to 100');
t.equals(queue.parallelTasks, 5, 'should have `parallelTasks` property default to 5');
t.equals(typeof queue.processTask, 'function', 'should have `processTask` method');
t.end();
});
test('Queue#processTask (simple)', (() => {
var _ref = _asyncToGenerator(function* (t) {
let queue = new Queue();
let task = (() => {
var _ref2 = _asyncToGenerator(function* () {
yield sleep(10);
return 'foo';
});
return function task() {
return _ref2.apply(this, arguments);
};
})();
let result = yield queue.processTask(task);
t.equals(result, 'foo', 'should process async task');
});
return function (_x) {
return _ref.apply(this, arguments);
};
})());
test('Queue#processTask (complex)', (() => {
var _ref3 = _asyncToGenerator(function* (t) {
const CONSTRAINT_PERIOD = 100;
const TASKS_PER_PERIOD = 3;
const PARALLEL_TASK_COUNT = 2;
let queue = new Queue({
period: CONSTRAINT_PERIOD,
tasksPerPeriod: TASKS_PER_PERIOD,
parallelTasks: PARALLEL_TASK_COUNT
});
let startTime = Date.now();
let getCurTime = function getCurTime() {
return Date.now() - startTime;
};
let timeLog = [];
function getAsyncTask(number, executionTime) {
timeLog.push({ number: number, added: getCurTime() });
return _asyncToGenerator(function* () {
timeLog.push({ number: number, started: getCurTime() });
yield sleep(executionTime);
timeLog.push({ number: number, processed: getCurTime() });
return number;
});
}
let tasks = [queue.processTask(getAsyncTask(0, 20)), queue.processTask(getAsyncTask(1, 60)), queue.processTask(getAsyncTask(2, 130)), queue.processTask(getAsyncTask(3, 20)), queue.processTask(getAsyncTask(4, 30)), queue.processTask(getAsyncTask(5, 30)), queue.processTask(getAsyncTask(6, 70)), queue.processTask(getAsyncTask(7, 170))];
yield sleep(100);
tasks.push(queue.processTask(getAsyncTask(8, 20)));
yield sleep(10);
tasks.push(queue.processTask(getAsyncTask(9, 20)));
yield sleep(10);
tasks.push(queue.processTask(getAsyncTask(10, 70)));
yield sleep(10);
tasks.push(queue.processTask(getAsyncTask(11, 20)));
let tasksResults = yield Promise.all(tasks);
t.deepEqual(tasksResults, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 'should return tasks results');
let timeline = timeLog.reduce(function (res, log) {
res[log.number] = Object.assign(res[log.number] || {}, log);
return res;
}, []);
// Задачи выполняются последовательно
timeline.reduce(function (prev, next) {
if (prev.started > next.started) {
t.fail(`task#${prev.number} start before task#${next.number}`);
}
return next;
});
// Не более заданного кол-ва одновременно исполняемых задач
for (let task1 of timeline) {
let parallelTasks = 0;
for (let task2 of timeline) {
if (task1 !== task2) {
var _ref5 = [task1.started, task2.started, task2.processed];
let a1 = _ref5[0],
a2 = _ref5[1],
b2 = _ref5[2];
if (a2 <= a1 && a1 < b2) {
parallelTasks++;
}
}
}
if (parallelTasks > PARALLEL_TASK_COUNT - 1) {
t.fail(`more than ${PARALLEL_TASK_COUNT - 1} tasks at the same time for task#${task1.number}`);
}
}
// Не более заданного кол-ва задач за указанных период
for (let task1 of timeline) {
let periodStart = task1.started - CONSTRAINT_PERIOD;
let periodTasks = timeline.filter(function (task2) {
if (task2 !== task1) {
return task2.started >= periodStart && task2.started < task1.started;
}
});
if (periodTasks.length > TASKS_PER_PERIOD) {
t.fail(`more than ${TASKS_PER_PERIOD} tasks for task#${task1.number}`);
}
}
// console.log(timeline)
});
return function (_x2) {
return _ref3.apply(this, arguments);
};
})());