UNPKG

@rpldy/uploader

Version:

the processing and queuing engine for react-uploady

144 lines 4.54 kB
import { FILE_STATES, logger } from "@rpldy/shared"; import { UPLOADER_EVENTS } from "../consts"; import processFinishedRequest from "./processFinishedRequest"; import { getItemsPrepareUpdater } from "./preSendPrepare"; import { getIsItemFinalized } from "./itemHelpers"; import { getBatchDataFromItemId } from "./batchHelpers"; const preparePreRequestItems = getItemsPrepareUpdater(UPLOADER_EVENTS.REQUEST_PRE_SEND, items => items, (items, options) => ({ items, options })); const updateUploadingState = (queue, items, sendResult) => { queue.updateState(state => { items.forEach(bi => { const item = state.items[bi.id]; item.state = FILE_STATES.UPLOADING; state.aborts[bi.id] = sendResult.abort; }); }); }; const sendAllowedItems = (queue, itemsSendData, next) => { const { items, options } = itemsSendData; const batch = queue.getState().batches[items[0].batchId]?.batch; if (batch) { let sendResult; try { sendResult = queue.sender.send(items, batch, options); } catch (ex) { logger.debugLog(`uploader.queue: sender failed with unexpected error`, ex); sendResult = { request: Promise.resolve({ status: 0, state: FILE_STATES.ERROR, response: ex.message }), abort: () => false, senderType: "exception-handler" }; } const { request } = sendResult; updateUploadingState(queue, items, sendResult); request.then(requestInfo => { const finishedData = items.map(item => ({ id: item.id, info: requestInfo })); processFinishedRequest(queue, finishedData, next); }); } }; const reportCancelledItems = (queue, items, cancelledResults, next) => { const cancelledItemsIds = cancelledResults.map((isCancelled, index) => isCancelled ? items[index].id : null).filter(Boolean); if (cancelledItemsIds.length) { const finishedData = cancelledItemsIds.map(id => ({ id, info: { status: 0, state: FILE_STATES.CANCELLED, response: "cancel" } })); processFinishedRequest(queue, finishedData, next); } return !!cancelledItemsIds.length; }; const reportPreparedError = (error, queue, items, next) => { const finishedData = items.map(({ id }) => ({ id, info: { status: 0, state: FILE_STATES.ERROR, response: error } })); processFinishedRequest(queue, finishedData, next); }; const getAllowedItem = (id, queue) => { const item = queue.getState().items[id]; return item && !getIsItemFinalized(item) ? item : undefined; }; const processAllowedItems = ({ allowedItems, cancelledResults, queue, items, ids, next }) => { const afterPreparePromise = allowedItems.length ? preparePreRequestItems(queue, allowedItems) : Promise.resolve(); let finalCancelledResults = cancelledResults; return afterPreparePromise.catch(err => { logger.debugLog("uploader.queue: encountered error while preparing items for request", err); reportPreparedError(err, queue, items, next); }).then(itemsSendData => { let nextP; if (itemsSendData) { if (itemsSendData.cancelled) { finalCancelledResults = ids.map(() => true); } else { const hasAborted = itemsSendData.items.some(item => getIsItemFinalized(item)); if (!hasAborted) { sendAllowedItems(queue, { items: itemsSendData.items, options: itemsSendData.options }, next); } else { logger.debugLog("uploader.queue: send data contains aborted items - not sending"); } } } if (!reportCancelledItems(queue, items, finalCancelledResults, next)) { nextP = next(queue); } return nextP; }); }; const processBatchItems = (queue, ids, next) => { const state = queue.getState(); let items = Object.values(state.items); items = items.filter(item => ids.includes(item.id) && !getIsItemFinalized(item)); return Promise.all(items.map(i => { const { batchOptions } = getBatchDataFromItemId(queue, i.id); return queue.runCancellable(UPLOADER_EVENTS.ITEM_START, i, batchOptions); })).then(cancelledResults => { let allowedItems = cancelledResults.map((isCancelled, index) => isCancelled ? null : getAllowedItem(items[index].id, queue)).filter(Boolean); return { allowedItems, cancelledResults, queue, items, ids, next }; }).then(processAllowedItems); }; export default processBatchItems;