/*
* site-monitor/services/batch.js Copyright 2021 cPanel, L.L.C.
* All rights reserved.
* copyright@cpanel.net http://cpanel.net
* This code is subject to the cPanel license. Unauthorized copying is prohibited
*/
/* global define, PAGE */
/** @namespace cpanel.siteMonitor.services.batch */
define(
[
"angular"
],
function(angular) {
"use strict";
var app = angular.module("cpanel.siteMonitor.batchService", []);
app.factory("batch", [
"$q",
function($q) {
return {
/**
* Perform the `op` on each item in the list in groups of `batchSize`. No more than `batchSize`
* Promises are running at once so the queue is not flooded.
*
* @async
* @template A
* @template B
* @param {A[]} list - list of items to operate on
* @param {number} batchSize - the number of items to process in parallel
* @param {Function(A) => Promise<B>} op - operation to perform on each item in the list
* @param {Function(A) => Identity<A>} gitId - a function that returns a string that uniquely identifies the item.
* @param {Function(A, string?) => void} doneItem - a function that is called after each op(item) call resolves(A) or rejects(A, error).
* @returns {Object.<string, B>} - a dictionary of the unique ids and the responses for that unique id.
*/
uniform: function uniform(list, batchSize, op, getId, doneItem) {
var length = list.length;
var responses = {};
var i = 0;
return new $q(function(resolve, reject) {
(function loop() {
if (i < length) {
// Create a list of promises
var requests = list
.slice(i, i + batchSize)
.map(function(item) {
return op(item)
.then(function(response) {
responses[ getId(item) ] = response;
if (doneItem) {
doneItem(item);
}
})
.catch(function(error) {
if (doneItem) {
doneItem(item, error);
}
});
});
// Wait for the current batch of ops to run
return $q.all(requests)
.finally(function() {
i += batchSize;
// Recurse into the next batch
loop();
});
} else {
resolve(responses); // Resolve the outer promise
}
})();
});
}
}
}
]);
}
);