storage: make remove and removeDir async

This commit is contained in:
Girish Ramakrishnan
2022-04-14 16:07:01 -05:00
parent 8d8cdd38a9
commit 685bda35b9
7 changed files with 88 additions and 139 deletions

View File

@@ -39,6 +39,7 @@ const assert = require('assert'),
path = require('path'),
S3BlockReadStream = require('s3-block-read-stream'),
safe = require('safetydance'),
util = require('util'),
_ = require('underscore');
let aws = AwsSdk;
@@ -385,10 +386,9 @@ function copy(apiConfig, oldFilePath, newFilePath) {
return events;
}
function remove(apiConfig, filename, callback) {
async function remove(apiConfig, filename) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof filename, 'string');
assert.strictEqual(typeof callback, 'function');
const credentials = getS3Config(apiConfig);
@@ -402,57 +402,48 @@ function remove(apiConfig, filename, callback) {
};
// deleteObjects does not return error if key is not found
s3.deleteObjects(deleteParams, function (error) {
if (error) return callback(new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. error: ${error.message || error.code}`)); // DO sets 'code'
callback(null);
});
const [error] = await safe(s3.deleteObjects(deleteParams).promise());
if (error) throw new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. error: ${error.message}`);
}
function removeDir(apiConfig, pathPrefix) {
async function removeDir(apiConfig, pathPrefix, progressCallback) {
assert.strictEqual(typeof apiConfig, 'object');
assert.strictEqual(typeof pathPrefix, 'string');
assert.strictEqual(typeof progressCallback, 'function');
const events = new EventEmitter();
let total = 0;
const credentials = getS3Config(apiConfig);
const s3 = new aws.S3(credentials);
const listDirAsync = util.promisify(listDir);
listDir(apiConfig, pathPrefix, 1000, function listDirIterator(entries, done) {
let total = 0;
await listDirAsync(apiConfig, pathPrefix, 1000, function listDirIterator(entries, done) {
total += entries.length;
const chunkSize = apiConfig.deleteConcurrency || (apiConfig.provider !== 'digitalocean-spaces' ? 1000 : 100); // throttle objects in each request
var chunks = chunk(entries, chunkSize);
const chunks = chunk(entries, chunkSize);
async.eachSeries(chunks, function deleteFiles(objects, iteratorCallback) {
var deleteParams = {
async.eachSeries(chunks, async function deleteFiles(objects) {
const deleteParams = {
Bucket: apiConfig.bucket,
Delete: {
Objects: objects.map(function (o) { return { Key: o.fullPath }; })
}
};
events.emit('progress', `Removing ${objects.length} files from ${objects[0].fullPath} to ${objects[objects.length-1].fullPath}`);
progressCallback({ message: `Removing ${objects.length} files from ${objects[0].fullPath} to ${objects[objects.length-1].fullPath}` });
// deleteObjects does not return error if key is not found
s3.deleteObjects(deleteParams, function (error /*, deleteData */) {
if (error) {
events.emit('progress', `Unable to remove ${deleteParams.Key} ${error.message || error.code}`);
return iteratorCallback(new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. error: ${error.message || error.code}`)); // DO sets 'code'
}
iteratorCallback(null);
});
const [error] = await safe(s3.deleteObjects(deleteParams).promise());
if (error) {
progressCallback({ message: `Unable to remove ${deleteParams.Key} ${error.message || error.code}` });
throw new BoxError(BoxError.EXTERNAL_ERROR, `Unable to remove ${deleteParams.Key}. error: ${error.message}`);
}
}, done);
}, function (error) {
events.emit('progress', `Removed ${total} files`);
process.nextTick(() => events.emit('done', error));
});
return events;
progressCallback({ message: `Removed ${total} files` });
}
async function remount(apiConfig) {