AWS Lambda NodeJS s3.DeleteObjects 有时会调用两次
AWS Lambda NodeJS s3.DeleteObjects sometimes called twice
我想使用 Lambda 函数 (NodeJS) 删除特定存储桶中最旧的文件。我正在开发该功能并且仍在测试(因此,目前没有触发器)。
每件事都适用于所有承诺,但函数 s3.deleteObjects 有时会为单个对象调用两次。
例如,该函数为对象“folder-A”调用两次,为对象“Folder-B”调用一次。如果我执行一项新测试,也许该函数会被调用一次(如我所料)。这似乎是一种随机行为。
我没有错误。
这是我的代码:
// Get folder's last modified date
const allFolders = ['object-1', 'object-2', 'object-3'];
const promises = allFolders.map(folderName => new Promise((resolve, reject) => {
s3.getObject({ Bucket: bucketName, Key: folderName }, function(err, data) {
if(err){
console.log('** ERRORE **', bucketName, folderName, err);
return reject(err);
}else{
resolve({Key: folderName, LastModified: data.LastModified});
}
});
}));
Promise.all(promises).then(foldersData => {
'here I sort the objects by LastModified... and the result is var foldersToDelete'
const foldersToDelete = ['object-2', 'object-3'];
//delete objects
// I call listAndDeleteObjects from an external file called functions.js
functions.listAndDeleteObjects(bucketName, foldersToDelete);
});
function.js这里
function listAndDeleteObjects (bucketName, foldersToDelete){
if (foldersToDelete.length === 0){
console.log('No objects found: exit');
return;
}
//list and delete all objects inside every folder
foldersToDelete.forEach( async (folderName, index) => {
//get all folder's objects
// listObjects returns all objects inside path folderName. In my example it returns only 'object-2' and 'object-3'
const folderObjects = (await listObjects(bucketName, folderName)).Contents.map( item => {
return {Key: item.Key}
});
//delete folder's objects
await mydeleteObjects(bucketName, folderObjects);
}
);
}
async function mydeleteObjects (bucketName, folderObjects) {
const deleteParams = {
Bucket: bucketName,
Delete: {
Objects: folderObjects
}
}
// **HERE THE PROBLEM**. s3.deleteObjects sometimes is called twice!
// for example 3.deleteObjects will "delete" object-2 two times and object-3 one time.
// if I execute a test again (after recreating object in s3 bucket), maybe it will delete object-3 twice and object-2 one, or object-3 and 2 one time...
await s3.deleteObjects(deleteParams, function(err,data){
if (deleteParams.Delete.Objects.length === 0){
console.log('No objects to delete found: exit');
return;
}
if (err) console.log(err,err.stack);
else{
console.log("End deleting objects:",data);
}
}).promise();
}
谁能解释一下为什么?
谢谢
我找到了解决方案。
我以错误的方式使用 'async' 和 'await',而不是在 s3.getObject 中使用回调函数,现在我使用 .then .
这里是代码:
try{
const listBucketParams = {
Bucket: bucketName,
Prefix: prefix,
Delimiter: '/'
};
// Get all bucket folders
allFolders = (await s3.listObjectsV2(listBucketParams).promise()).CommonPrefixes.map(item => item.Prefix);
const promises = allFolders.map(folderName => new Promise( (resolve, reject) => {
//get folder's LastModified date
s3.getObject({ Bucket: bucketName, Key: folderName })
.promise()
.then(response => {
resolve({Key: folderName, LastModified: response.LastModified});
})
.catch(async e => {
if(e.code === 'NoSuchKey'){
//this function retrieves one object from the folderName s3 folder
functions.listFolderObject(bucketName, folderName, resolve);
}
});
}));
await Promise.all(promises).then(async foldersData => {
// sort folders by date desc
foldersData.sort((a,b) => (a.LastModified < b.LastModified) ? 1 : ((b.LastModified < a.LastModified) ? -1 : 0));
// get folders to delete
const foldersToDelete = functions.getfoldersToDelete(foldersData, objectsToPreserve, isDevEnv);
//delete objects
await functions.listAndDeleteObjects(bucketName, foldersToDelete);
});
} catch (e){
}
我想使用 Lambda 函数 (NodeJS) 删除特定存储桶中最旧的文件。我正在开发该功能并且仍在测试(因此,目前没有触发器)。
每件事都适用于所有承诺,但函数 s3.deleteObjects 有时会为单个对象调用两次。 例如,该函数为对象“folder-A”调用两次,为对象“Folder-B”调用一次。如果我执行一项新测试,也许该函数会被调用一次(如我所料)。这似乎是一种随机行为。 我没有错误。
这是我的代码:
// Get folder's last modified date
const allFolders = ['object-1', 'object-2', 'object-3'];
const promises = allFolders.map(folderName => new Promise((resolve, reject) => {
s3.getObject({ Bucket: bucketName, Key: folderName }, function(err, data) {
if(err){
console.log('** ERRORE **', bucketName, folderName, err);
return reject(err);
}else{
resolve({Key: folderName, LastModified: data.LastModified});
}
});
}));
Promise.all(promises).then(foldersData => {
'here I sort the objects by LastModified... and the result is var foldersToDelete'
const foldersToDelete = ['object-2', 'object-3'];
//delete objects
// I call listAndDeleteObjects from an external file called functions.js
functions.listAndDeleteObjects(bucketName, foldersToDelete);
});
function.js这里
function listAndDeleteObjects (bucketName, foldersToDelete){
if (foldersToDelete.length === 0){
console.log('No objects found: exit');
return;
}
//list and delete all objects inside every folder
foldersToDelete.forEach( async (folderName, index) => {
//get all folder's objects
// listObjects returns all objects inside path folderName. In my example it returns only 'object-2' and 'object-3'
const folderObjects = (await listObjects(bucketName, folderName)).Contents.map( item => {
return {Key: item.Key}
});
//delete folder's objects
await mydeleteObjects(bucketName, folderObjects);
}
);
}
async function mydeleteObjects (bucketName, folderObjects) {
const deleteParams = {
Bucket: bucketName,
Delete: {
Objects: folderObjects
}
}
// **HERE THE PROBLEM**. s3.deleteObjects sometimes is called twice!
// for example 3.deleteObjects will "delete" object-2 two times and object-3 one time.
// if I execute a test again (after recreating object in s3 bucket), maybe it will delete object-3 twice and object-2 one, or object-3 and 2 one time...
await s3.deleteObjects(deleteParams, function(err,data){
if (deleteParams.Delete.Objects.length === 0){
console.log('No objects to delete found: exit');
return;
}
if (err) console.log(err,err.stack);
else{
console.log("End deleting objects:",data);
}
}).promise();
}
谁能解释一下为什么? 谢谢
我找到了解决方案。 我以错误的方式使用 'async' 和 'await',而不是在 s3.getObject 中使用回调函数,现在我使用 .then .
这里是代码:
try{
const listBucketParams = {
Bucket: bucketName,
Prefix: prefix,
Delimiter: '/'
};
// Get all bucket folders
allFolders = (await s3.listObjectsV2(listBucketParams).promise()).CommonPrefixes.map(item => item.Prefix);
const promises = allFolders.map(folderName => new Promise( (resolve, reject) => {
//get folder's LastModified date
s3.getObject({ Bucket: bucketName, Key: folderName })
.promise()
.then(response => {
resolve({Key: folderName, LastModified: response.LastModified});
})
.catch(async e => {
if(e.code === 'NoSuchKey'){
//this function retrieves one object from the folderName s3 folder
functions.listFolderObject(bucketName, folderName, resolve);
}
});
}));
await Promise.all(promises).then(async foldersData => {
// sort folders by date desc
foldersData.sort((a,b) => (a.LastModified < b.LastModified) ? 1 : ((b.LastModified < a.LastModified) ? -1 : 0));
// get folders to delete
const foldersToDelete = functions.getfoldersToDelete(foldersData, objectsToPreserve, isDevEnv);
//delete objects
await functions.listAndDeleteObjects(bucketName, foldersToDelete);
});
} catch (e){
}