@rpldy/uploader
Version:
the processing and queuing engine for react-uploady
109 lines • 3.61 kB
JavaScript
import { logger, FILE_STATES } from "@rpldy/shared";
import processBatchItems from "./processBatchItems";
import { getIsBatchReady, isNewBatchStarting, cancelBatchForItem, loadNewBatchForItem, failBatchForItem, isItemBatchStartPending } from "./batchHelpers";
const getIsItemInActiveRequest = (queue, itemId) => {
return queue.getState().activeIds.flat().includes(itemId);
};
const getIsItemReady = item => item.state.valueOf() === FILE_STATES.ADDED.valueOf();
export const findNextItemIndex = queue => {
const state = queue.getState(),
itemQueue = state.itemQueue,
items = state.items;
let nextItemId = null,
batchIndex = 0,
itemIndex = 0,
batchId = state.batchQueue[batchIndex];
while (batchId && !nextItemId) {
if (getIsBatchReady(queue, batchId)) {
nextItemId = itemQueue[batchId][itemIndex];
while (nextItemId && (getIsItemInActiveRequest(queue, nextItemId) || !getIsItemReady(items[nextItemId]))) {
itemIndex += 1;
nextItemId = itemQueue[batchId][itemIndex];
}
}
if (!nextItemId) {
batchIndex += 1;
batchId = state.batchQueue[batchIndex];
itemIndex = 0;
}
}
return nextItemId ? [batchId, itemIndex] : null;
};
export const getNextIdGroup = queue => {
const state = queue.getState(),
itemQueue = state.itemQueue,
[nextBatchId, nextItemIndex] = findNextItemIndex(queue) || [];
let nextId = nextBatchId && ~nextItemIndex ? itemQueue[nextBatchId][nextItemIndex] : null,
nextGroup;
if (nextId) {
const {
batchOptions
} = state.batches[nextBatchId],
groupMax = batchOptions.maxGroupSize || 0;
if (batchOptions.grouped && groupMax > 1) {
const batchItems = state.itemQueue[nextBatchId];
nextGroup = batchItems.slice(nextItemIndex, nextItemIndex + groupMax);
} else {
nextGroup = [nextId];
}
}
return nextGroup;
};
const updateItemsAsActive = (queue, ids) => {
queue.updateState(state => {
state.activeIds = state.activeIds.concat(ids);
});
};
const processNextWithBatch = (queue, ids) => {
let newBatchP;
if (!isItemBatchStartPending(queue, ids[0])) {
updateItemsAsActive(queue, ids);
if (isNewBatchStarting(queue, ids[0])) {
newBatchP = loadNewBatchForItem(queue, ids[0]).then(allowBatch => {
let cancelled = !allowBatch;
if (cancelled) {
cancelBatchForItem(queue, ids[0]);
processNext(queue);
}
return cancelled;
}).catch(err => {
logger.debugLog("uploader.processor: encountered error while preparing batch for request", err);
failBatchForItem(queue, ids[0], err);
processNext(queue);
return true;
});
} else {
newBatchP = Promise.resolve(false);
}
} else {
newBatchP = Promise.resolve(true);
}
return newBatchP;
};
const processNext = queue => {
let processPromise;
const ids = getNextIdGroup(queue);
if (ids) {
const currentCount = queue.getCurrentActiveCount(),
{
concurrent = !!0,
maxConcurrent = 0
} = queue.getOptions();
if (!currentCount || concurrent && currentCount < maxConcurrent) {
logger.debugLog("uploader.processor: Processing next upload - ", {
ids,
currentCount
});
processPromise = processNextWithBatch(queue, ids).then(failedOrCancelled => {
if (!failedOrCancelled) {
processBatchItems(queue, ids, processNext);
if (concurrent) {
processNext(queue);
}
}
});
}
}
return processPromise;
};
export default processNext;