fix condition where message was not inserted if a partially stored attachment already existed

This commit is contained in:
Andris Reinman 2017-09-13 12:48:43 +03:00
parent 29c7311fbf
commit f117a6f6d9
2 changed files with 33 additions and 6 deletions

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ npm-debug.log
.npmrc
config/production.*
config/development.*
package-lock.json*
emails/*
!emails/README.md

View file

@ -35,9 +35,7 @@ class GridstoreStorage {
create(attachment, hash, callback) {
hash = Buffer.from(hash, 'hex');
let returned = false;
let retried = false;
let id = hash;
let metadata = {
@ -52,6 +50,7 @@ class GridstoreStorage {
}
});
let tryCount = 0;
let tryStore = () => {
this.gridfs.collection(this.bucketName + '.files').findOneAndUpdate({
_id: hash
@ -84,8 +83,11 @@ class GridstoreStorage {
}
if (err.code === 11000) {
// most probably a race condition, try again
if (!retried) {
retried = true;
if (tryCount++ < 5) {
if (/attachments\.chunks /.test(err.message)) {
// partial chunks for a probably deleted message detected, try to clean up
return setTimeout(() => this.cleanupGarbage(id, tryStore), 100 + 200 * Math.random());
}
return setTimeout(tryStore, 10);
}
}
@ -205,8 +207,8 @@ class GridstoreStorage {
// make sure that we do not delete a message that is already re-used
'metadata.c': 0,
'metadata.m': 0
}, (err, result) => {
if (err || !result.deletedCount) {
}, err => {
if (err) {
return processNext();
}
@ -227,6 +229,30 @@ class GridstoreStorage {
processNext();
}
cleanupGarbage(id, next) {
this.gridfs.collection('attachments.files').findOne({
_id: id
}, (err, file) => {
if (err) {
return next(err);
}
if (file) {
// attachment entry exists, do nothing
return next(null, false);
}
// orphaned attachment, delete data chunks
this.gridfs.collection('attachments.chunks').deleteMany({
files_id: id
}, (err, info) => {
if (err) {
return next(err);
}
next(null, info.deletedCount);
});
});
}
}
module.exports = GridstoreStorage;