function groupAndBatchGranules(granules, batchSize) {
  const filteredBatchSize = isNumber(batchSize) ? batchSize : 1;
  const granulesByCollectionMap = groupBy(
    granules,
    (g) => constructCollectionId(g.dataType, g.version)
  );
  const granulesBatchedByCollection = Object.values(granulesByCollectionMap).reduce(
    (arr, granulesByCollection) => arr.concat(chunk(granulesByCollection, filteredBatchSize)),
    []
  );
  return granulesBatchedByCollection.reduce((arr, granuleBatch) => arr.concat(
    Object.values(groupBy(granuleBatch, 'provider'))
  ), []);
}
/**
 * Group granules by collection and split into batches then split again on provider
 *
 * @param {Array<Object>} granules - list of input granules
 * @param {number} batchSize - size of batch of granules to queue
 * @returns {Array<Object>} list of lists of granules: each list contains granules which belong
 *                          to the same collection, and each list's max length is set by batchSize
 */
Group granules by collection and split into batches then split again on provider
@param {Array} granules - list of input granules
@param {number} batchSize - size of batch of granules to queue
@returns {Array} list of lists of granules: each list contains granules which belong
to the same collection, and each list's max length is set by batchSize
Group granules by collection and split into batches then split again on provider @param { Array } granules - list of input granules @param { number } batchSize - size of batch of granules to queue @returns { Array } list of lists of granules : each list contains granules which belong to the same collection and each list ' s max length is set by batchSize
function groupAndBatchGranules(granules, batchSize) {
  const filteredBatchSize = isNumber(batchSize) ? batchSize : 1;
  const granulesByCollectionMap = groupBy(
    granules,
    (g) => constructCollectionId(g.dataType, g.version)
  );
  const granulesBatchedByCollection = Object.values(granulesByCollectionMap).reduce(
    (arr, granulesByCollection) => arr.concat(chunk(granulesByCollection, filteredBatchSize)),
    []
  );
  return granulesBatchedByCollection.reduce((arr, granuleBatch) => arr.concat(
    Object.values(groupBy(granuleBatch, 'provider'))
  ), []);
}
function groupAndBatchGranules ( granules , batchSize ) { const filteredBatchSize = isNumber ( batchSize ) ? batchSize : 1 ; const granulesByCollectionMap = groupBy ( granules , ( g ) => constructCollectionId ( g . dataType , g . version ) ) ; const granulesBatchedByCollection = Object . values ( granulesByCollectionMap ) . reduce ( ( arr , granulesByCollection ) => arr . concat ( chunk ( granulesByCollection , filteredBatchSize ) ) , [ ] ) ; return granulesBatchedByCollection . reduce ( ( arr , granuleBatch ) => arr . concat ( Object . values ( groupBy ( granuleBatch , 'provider' ) ) ) , [ ] ) ; }
Group granules by collection and split into batches then split again on provider
 @param {Array<Object>} granules - list of input granules
 @param {number} batchSize - size of batch of granules to queue
 @returns {Array<Object>} list of lists of granules: each list contains granules which belong
                          to the same collection, and each list's max length is set by batchSize
Group granules by collection and split into batches then split again on provider @param { Array<Object > } granules - list of input granules @param { number } batchSize - size of batch of granules to queue @returns { Array<Object > } list of lists of granules : each list contains granules which belong to the same collection and each list ' s max length is set by batchSize