UNPKG

@rpldy/uploader

Version:

the processing and queuing engine for react-uploady

281 lines (280 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.triggerUploaderBatchEvent = exports.removePendingBatches = exports.removeBatchItems = exports.preparePendingForUpload = exports.loadNewBatchForItem = exports.isNewBatchStarting = exports.isItemBatchStartPending = exports.incrementBatchFinishedCounter = exports.getIsBatchReady = exports.getIsBatchFinalized = exports.getBatchFromState = exports.getBatchFromItemId = exports.getBatchDataFromItemId = exports.finalizeBatch = exports.failBatchForItem = exports.detachRecycledFromPreviousBatch = exports.clearBatchData = exports.cleanUpFinishedBatches = exports.cancelBatchWithId = exports.cancelBatchForItem = void 0; var _shared = require("@rpldy/shared"); var _simpleState = require("@rpldy/simple-state"); var _consts = require("../consts"); var _preSendPrepare = require("./preSendPrepare"); var _itemHelpers = require("./itemHelpers"); const prepareBatchStartItems = (0, _preSendPrepare.getItemsPrepareUpdater)(_consts.UPLOADER_EVENTS.BATCH_START, batch => batch.items, null, ({ batch } = { batch: false }) => { if (batch) { throw new Error(`BATCH_START event handlers cannot update batch data. Only items & options`); } }); const BATCH_READY_STATES = [_shared.BATCH_STATES.ADDED, _shared.BATCH_STATES.PROCESSING, _shared.BATCH_STATES.UPLOADING]; const BATCH_FINISHED_STATES = [_shared.BATCH_STATES.ABORTED, _shared.BATCH_STATES.CANCELLED, _shared.BATCH_STATES.FINISHED, _shared.BATCH_STATES.ERROR]; const getBatchFromState = (state, id) => state.batches[id].batch; exports.getBatchFromState = getBatchFromState; const getBatch = (queue, id) => { return getBatchFromState(queue.getState(), id); }; const getBatchDataFromItemId = (queue, itemId) => { const state = queue.getState(); const item = state.items[itemId]; return state.batches[item.batchId]; }; exports.getBatchDataFromItemId = getBatchDataFromItemId; const getBatchFromItemId = (queue, itemId) => { return getBatchDataFromItemId(queue, itemId).batch; }; exports.getBatchFromItemId = getBatchFromItemId; const removeBatchItems = (queue, batchId) => { const batch = getBatch(queue, batchId); batch.items.forEach(({ id }) => (0, _itemHelpers.finalizeItem)(queue, id, true)); }; exports.removeBatchItems = removeBatchItems; const removeBatch = (queue, batchId) => { queue.updateState(state => { delete state.batches[batchId]; delete state.itemQueue[batchId]; const batchQueueIndex = state.batchQueue.indexOf(batchId); if (~batchQueueIndex) { state.batchQueue.splice(batchQueueIndex, 1); } const pendingFlagIndex = state.batchesStartPending.indexOf(batchId); if (~pendingFlagIndex) { state.batchesStartPending.splice(pendingFlagIndex, 1); } }); }; const finalizeBatch = (queue, batchId, eventType, finalState = _shared.BATCH_STATES.FINISHED, additionalInfo) => { queue.updateState(state => { const batch = getBatchFromState(state, batchId); batch.state = finalState; if (additionalInfo) { batch.additionalInfo = additionalInfo; } }); triggerUploaderBatchEvent(queue, batchId, eventType); triggerUploaderBatchEvent(queue, batchId, _consts.UPLOADER_EVENTS.BATCH_FINALIZE); }; exports.finalizeBatch = finalizeBatch; const cancelBatchWithId = (queue, batchId) => { _shared.logger.debugLog("uploady.uploader.batchHelpers: cancelling batch: ", batchId); finalizeBatch(queue, batchId, _consts.UPLOADER_EVENTS.BATCH_CANCEL, _shared.BATCH_STATES.CANCELLED); removeBatchItems(queue, batchId); removeBatch(queue, batchId); }; exports.cancelBatchWithId = cancelBatchWithId; const cancelBatchForItem = (queue, itemId) => { if ((0, _itemHelpers.getIsItemExists)(queue, itemId)) { const data = getBatchDataFromItemId(queue, itemId), batchId = data?.batch.id; if (batchId) { cancelBatchWithId(queue, batchId); } else { _shared.logger.debugLog(`uploady.uploader.batchHelpers: cancel batch called for batch already removed (item id = ${itemId})`); } } }; exports.cancelBatchForItem = cancelBatchForItem; const failBatchForItem = (queue, itemId, err) => { const batch = getBatchFromItemId(queue, itemId), batchId = batch.id; _shared.logger.debugLog("uploady.uploader.batchHelpers: failing batch: ", { batch }); finalizeBatch(queue, batchId, _consts.UPLOADER_EVENTS.BATCH_ERROR, _shared.BATCH_STATES.ERROR, err.message); removeBatchItems(queue, batchId); removeBatch(queue, batchId); }; exports.failBatchForItem = failBatchForItem; const isItemBatchStartPending = (queue, itemId) => { const batch = getBatchFromItemId(queue, itemId); return queue.getState().batchesStartPending.includes(batch.id); }; exports.isItemBatchStartPending = isItemBatchStartPending; const isNewBatchStarting = (queue, itemId) => { const batch = getBatchFromItemId(queue, itemId); return queue.getState().currentBatch !== batch.id; }; exports.isNewBatchStarting = isNewBatchStarting; const loadNewBatchForItem = (queue, itemId) => { const batch = getBatchFromItemId(queue, itemId); queue.updateState(state => { state.batchesStartPending.push(batch.id); }); return prepareBatchStartItems(queue, batch).then(({ cancelled }) => { let alreadyFinished = false; queue.updateState(state => { const pendingFlagIndex = state.batchesStartPending.indexOf(batch.id); state.batchesStartPending.splice(pendingFlagIndex, 1); }); if (!cancelled) { alreadyFinished = !(0, _itemHelpers.getIsItemExists)(queue, itemId); if (!alreadyFinished) { queue.updateState(state => { state.currentBatch = batch.id; }); } } return !cancelled && !alreadyFinished; }); }; exports.loadNewBatchForItem = loadNewBatchForItem; const cleanUpFinishedBatches = queue => { (0, _shared.scheduleIdleWork)(() => { const state = queue.getState(); Object.keys(state.batches).forEach(batchId => { const { batch, finishedCounter } = state.batches[batchId]; const { orgItemCount } = batch; const alreadyFinalized = getIsBatchFinalized(batch); if (orgItemCount === finishedCounter) { if (!alreadyFinalized && batch.completed !== 100) { queue.updateState(state => { const batch = getBatchFromState(state, batchId); batch.completed = 100; batch.loaded = batch.items.reduce((res, { loaded }) => res + loaded, 0); }); triggerUploaderBatchEvent(queue, batchId, _consts.UPLOADER_EVENTS.BATCH_PROGRESS); } queue.updateState(state => { if (state.currentBatch === batchId) { state.currentBatch = null; } }); _shared.logger.debugLog(`uploady.uploader.batchHelpers: cleaning up batch: ${batch.id}`); if (!alreadyFinalized) { finalizeBatch(queue, batchId, _consts.UPLOADER_EVENTS.BATCH_FINISH); } removeBatchItems(queue, batchId); removeBatch(queue, batchId); } }); }); }; exports.cleanUpFinishedBatches = cleanUpFinishedBatches; const triggerUploaderBatchEvent = (queue, batchId, event) => { const state = queue.getState(), { batch, batchOptions } = state.batches[batchId], stateItems = state.items; const eventBatch = { ...(0, _simpleState.unwrap)(batch), items: batch.items.map(({ id }) => (0, _simpleState.unwrap)(stateItems[id])) }; queue.trigger(event, eventBatch, (0, _simpleState.unwrap)(batchOptions)); }; exports.triggerUploaderBatchEvent = triggerUploaderBatchEvent; const getIsBatchReady = (queue, batchId) => { const batch = getBatchFromState(queue.getState(), batchId); return BATCH_READY_STATES.includes(batch.state); }; exports.getIsBatchReady = getIsBatchReady; const detachRecycledFromPreviousBatch = (queue, item) => { const { previousBatch } = item; if (item.recycled && previousBatch && queue.getState().batches[previousBatch]) { const { id: batchId } = getBatchFromItemId(queue, item.id); if (batchId === previousBatch) { queue.updateState(state => { const batch = getBatchFromState(state, batchId); const index = batch.items.findIndex(({ id }) => id === item.id); if (~index) { batch.items.splice(index, 1); } if (state.batches[batchId].itemBatchOptions[item.id]) { delete state.batches[batchId].itemBatchOptions[item.id]; } }); } } }; exports.detachRecycledFromPreviousBatch = detachRecycledFromPreviousBatch; const preparePendingForUpload = (queue, uploadOptions) => { queue.updateState(state => { Object.keys(state.batches).forEach(batchId => { const batchData = state.batches[batchId]; const { batch, batchOptions } = batchData; if (batch.state === _shared.BATCH_STATES.PENDING) { batch.items.forEach(item => { item.state = _shared.FILE_STATES.ADDED; }); batch.state = _shared.BATCH_STATES.ADDED; batchData.batchOptions = (0, _shared.merge)({}, batchOptions, uploadOptions); } }); }); }; exports.preparePendingForUpload = preparePendingForUpload; const removePendingBatches = queue => { const batches = queue.getState().batches; Object.keys(batches).filter(batchId => batches[batchId].batch.state === _shared.BATCH_STATES.PENDING).forEach(batchId => { removeBatchItems(queue, batchId); removeBatch(queue, batchId); }); }; exports.removePendingBatches = removePendingBatches; const incrementBatchFinishedCounter = (queue, batchId) => { queue.updateState(state => { state.batches[batchId].finishedCounter += 1; }); }; exports.incrementBatchFinishedCounter = incrementBatchFinishedCounter; const getIsBatchFinalized = batch => BATCH_FINISHED_STATES.includes(batch.state); exports.getIsBatchFinalized = getIsBatchFinalized; const clearBatchData = (queue, batchId) => { queue.updateState(state => { const { items } = getBatchFromState(state, batchId); delete state.batches[batchId]; delete state.itemQueue[batchId]; const indx = state.batchQueue.indexOf(batchId); if (~indx) { state.batchQueue.splice(indx, 1); } if (state.currentBatch === batchId) { state.currentBatch = null; } items.forEach(({ id }) => { delete state.items[id]; const activeIndex = state.activeIds.indexOf(id); if (~activeIndex) { state.activeIds.splice(activeIndex, 1); } }); }); }; exports.clearBatchData = clearBatchData;