@okta/stormpath-migration
Version:
Migration tool to import Stormpath data into an Okta tenant
91 lines (84 loc) • 2.69 kB
JavaScript
/*!
* Copyright (c) 2017, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/
const Promise = require('bluebird');
function cancelEach(list) {
return () => {
list.length = 0;
};
}
async function processList(list, fn, cancelFn) {
while (list.length > 0) {
await fn(list.shift(), cancelFn);
}
}
/**
* Concurrently evaluates each item in a list (up to the limit) with the
* provided function. This function can be async, but must return a Promise to
* signal when it is complete.
*
* If an error should cancel any remaining operations, call the cancelFn to
* clear out the remainder of the list. If this is not called, list processing
* will continue processing in the background.
*
* @param {array} list
* @param {function} fn
* @param {number} limit
*/
async function each(list, fn, limit) {
const clone = list.slice();
const promises = [];
const cancelFn = cancelEach(list);
for (let i = 0; i < limit; i++) {
promises.push(processList(clone, fn, cancelFn));
}
await Promise.all(promises);
}
/**
* Evaluates a list with the provided function in batches of the limit. When
* a batch is finished, the batchFn is called with the total number of
* processed items. The evalFn and batchFn can both by async.
*
* @param {array} list
* @param {function} evalFn
* @param {function} batchFn
* @param {number} limit
*/
async function batch(list, evalFn, batchFn, limit) {
let numProcessed = 0;
while (list.length > 0) {
const promises = [];
for (let i = 0; i < limit; i++) {
if (list.length === 0) {
break;
}
const item = list.shift();
promises.push(evalFn(item));
numProcessed++;
}
await Promise.all(promises);
await batchFn(numProcessed);
}
}
/**
* Concurrently evaluates each item in a list (up to the limit) with the
* provided mapping function, and returns the constructed map.
*
* @param {array} list
* @param {function} fn
* @param {number} limit
*/
async function mapToObject(list, fn, limit) {
const map = {};
await each(list, item => fn(item, map), limit);
return map;
}
module.exports = { each, batch, mapToObject };