You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.9 KiB
JavaScript
69 lines
1.9 KiB
JavaScript
6 months ago
|
'use strict';
|
||
|
|
||
|
const { default: pRetry } = require('@fullstax/p-retry');
|
||
|
|
||
|
/**
|
||
|
* Creates an async queue processor.
|
||
|
* 不同 itemId 的数据并发处理
|
||
|
* 每个 itemId 的数据有序地仅处理一个, 先进先出
|
||
|
* @param {Function} processItemFn - The function to process each item in the queue.
|
||
|
* @param {Object} [options] - Options for the queue processor.
|
||
|
* @param {Object} [options.retryOptions] - Options for retrying failed items.
|
||
|
* @param {number} [options.retryOptions.retries] - Number of retries for failed items.
|
||
|
* @returns {Object} - An object with an enqueue method to add items tothe queue.
|
||
|
*/
|
||
|
async function createAsyncQueueProcessor(processItemFn, options = {}) {
|
||
|
if (typeof processItemFn !== 'function') {
|
||
|
throw new Error('processItemFn must be a function');
|
||
|
}
|
||
|
|
||
|
const { retryOptions = { retries: 0 } } = options;
|
||
|
const queues = new Map();
|
||
|
const processing = new Map();
|
||
|
|
||
|
async function processQueue(itemId) {
|
||
|
if (processing.get(itemId)) {
|
||
|
return; // processing
|
||
|
}
|
||
|
|
||
|
processing.set(itemId, true);
|
||
|
|
||
|
try {
|
||
|
const queue = queues.get(itemId);
|
||
|
if (!queue) return;
|
||
|
|
||
|
while (queue.length > 0) {
|
||
|
const item = queue.shift();
|
||
|
try {
|
||
|
if (retryOptions.retries > 0) {
|
||
|
await pRetry(async () => {
|
||
|
await processItemFn(item);
|
||
|
}, retryOptions);
|
||
|
} else {
|
||
|
await processItemFn(item);
|
||
|
}
|
||
|
} catch (itemError) {
|
||
|
console.error(`Error processing item ${JSON.stringify(item)}:\n`, itemError);
|
||
|
// Handle error (e.g., retry, log, DLQ)
|
||
|
}
|
||
|
}
|
||
|
queues.delete(itemId); // Clean up empty queue
|
||
|
} finally {
|
||
|
processing.set(itemId, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function enqueue(itemId, itemData) {
|
||
|
if (!queues.has(itemId)) {
|
||
|
queues.set(itemId, []);
|
||
|
}
|
||
|
|
||
|
queues.get(itemId).push(itemData);
|
||
|
processQueue(itemId);
|
||
|
}
|
||
|
|
||
|
return { enqueue };
|
||
|
}
|
||
|
|
||
|
module.exports = createAsyncQueueProcessor;
|