@rpldy/uploader
Version:
the processing and queuing engine for react-uploady
281 lines (280 loc) • 10.6 kB
JavaScript
;
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;