mirror of
https://github.com/wassname/talk.git
synced 2026-06-29 22:01:13 +08:00
108 lines
2.7 KiB
JavaScript
108 lines
2.7 KiB
JavaScript
const debug = require('debug')('talk:services:migration');
|
|
|
|
/**
|
|
* processUpdates processes batches of updates on the given model.
|
|
*
|
|
* @param {Object} model mongoose model that should perform the operations on
|
|
* @param {Array<Object>} updates array of updates to execute
|
|
*/
|
|
const processUpdates = async (model, updates) => {
|
|
// Create a new batch operation.
|
|
const bulk = model.collection.initializeUnorderedBulkOp();
|
|
|
|
for (const { query, update } of updates) {
|
|
bulk.find(query).updateOne(update);
|
|
}
|
|
|
|
// Execute the bulk update operation.
|
|
await bulk.execute();
|
|
};
|
|
|
|
const debugProcessStatistics = (count, totalCount) => {
|
|
if (totalCount > 0) {
|
|
debug(
|
|
`processed ${(count / totalCount * 100).toFixed(
|
|
2
|
|
)}% (${count}/${totalCount}) updates`
|
|
);
|
|
} else {
|
|
debug(`processed ${count} updates`);
|
|
}
|
|
};
|
|
|
|
const transformSingleWithCursor = ({
|
|
queryBatchSize,
|
|
updateBatchSize,
|
|
}) => async (query, process, Model) => {
|
|
debug('starting transform');
|
|
|
|
// We'll manage the updates that we store inside this object.
|
|
let updates = [];
|
|
|
|
// Count the elements in the transformation.
|
|
let totalCount = 0;
|
|
try {
|
|
totalCount = await query.count();
|
|
} catch (err) {}
|
|
|
|
// First we'll collect all the individual actions with specific group id's.
|
|
const cursor = await query.batchSize(queryBatchSize);
|
|
|
|
let count = 0;
|
|
while (await cursor.hasNext()) {
|
|
const result = await cursor.next();
|
|
|
|
const transformed = await process(result);
|
|
if (transformed) {
|
|
updates.push(transformed);
|
|
}
|
|
|
|
if (updates.length > updateBatchSize) {
|
|
// Process the updates.
|
|
await processUpdates(Model, updates);
|
|
count += updates.length;
|
|
debugProcessStatistics(count, totalCount);
|
|
|
|
// Clear the updates array.
|
|
updates = [];
|
|
}
|
|
}
|
|
|
|
if (updates.length > 0) {
|
|
// Process the updates.
|
|
await processUpdates(Model, updates);
|
|
count += updates.length;
|
|
debugProcessStatistics(count, totalCount);
|
|
|
|
// Clear the updates array.
|
|
updates = [];
|
|
}
|
|
|
|
debug('finished transform');
|
|
};
|
|
|
|
/**
|
|
* processManyUpdates processes batches of updates on many models with the given
|
|
* model.
|
|
*
|
|
* @param {Object} model mongoose model that should perform the operations on
|
|
* @param {Array<Object>} updates array of updates to execute
|
|
*/
|
|
const processManyUpdates = async (model, updates) => {
|
|
// Create a new batch operation.
|
|
const bulk = model.collection.initializeUnorderedBulkOp();
|
|
|
|
for (const { query, update } of updates) {
|
|
bulk.find(query).update(update);
|
|
}
|
|
|
|
// Execute the bulk update operation.
|
|
await bulk.execute();
|
|
};
|
|
|
|
module.exports = ctx => ({
|
|
processManyUpdates,
|
|
processUpdates,
|
|
transformSingleWithCursor: transformSingleWithCursor(ctx),
|
|
});
|