Skip to content

Commit 2de80d5

Browse files
Add checks in MongoClientInterface
- We should ensure we consider properly the returned flags from MongoDB. - The coverage of MongoClientInterface is increased as well, to also test the new logic. Issue: ARSN-488
1 parent d79a54b commit 2de80d5

File tree

5 files changed

+2261
-48
lines changed

5 files changed

+2261
-48
lines changed

lib/storage/metadata/mongoclient/MongoClientInterface.ts

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,11 @@ class MongoClientInterface {
417417
}, payload, {
418418
upsert: true,
419419
})
420-
.then(() => {
420+
.then(result => {
421+
if (result.modifiedCount === 0 && result.upsertedCount === 0) {
422+
log.debug('createBucket: failed to create bucket', { bucketName });
423+
return cb(errors.InternalError);
424+
}
421425
// caching bucket vFormat
422426
this.bucketVFormatCache.add(bucketName, payload.$set.vFormat);
423427
// NOTE: We do not need to create a collection for
@@ -583,7 +587,13 @@ class MongoClientInterface {
583587
}, {
584588
upsert: true,
585589
})
586-
.then(() => cb(null))
590+
.then(result => {
591+
if (result.modifiedCount === 0 && result.upsertedCount === 0) {
592+
log.debug('putBucketAttributes: failed to update bucket', { bucketName });
593+
return cb(errors.InternalError);
594+
}
595+
return cb(null);
596+
})
587597
.catch(err => {
588598
log.error(
589599
'putBucketAttributes: error putting bucket attributes',
@@ -623,7 +633,13 @@ class MongoClientInterface {
623633
},
624634
}, {
625635
upsert: true,
626-
}).then(() => cb(null)).catch(err => {
636+
}).then(result => {
637+
if (result.modifiedCount === 0 && result.upsertedCount === 0) {
638+
log.error('putBucketAttributesCapabilities: failed to update bucket', { bucketName });
639+
return cb(errors.InternalError);
640+
}
641+
return cb(null);
642+
}).catch(err => {
627643
log.error(
628644
'putBucketAttributesCapabilities: error putting bucket attributes',
629645
{ error: err.message });
@@ -657,7 +673,14 @@ class MongoClientInterface {
657673
$unset: {
658674
[updateString]: '',
659675
},
660-
}).then(() => cb(null)).catch(err => {
676+
}).then(result => {
677+
if (result.modifiedCount === 0) {
678+
log.debug('deleteBucketAttributesCapability: bucket not found or capability not present',
679+
{ bucketName });
680+
return cb(errors.NoSuchBucket);
681+
}
682+
return cb(null);
683+
}).catch(err => {
661684
if (err) {
662685
log.error(
663686
'deleteBucketAttributesCapability: error deleting bucket attributes',
@@ -1967,7 +1990,19 @@ class MongoClientInterface {
19671990
if (params && params.doesNotNeedOpogUpdate) {
19681991
// If flag is true, directly delete object
19691992
return collection.deleteOne(deleteFilter)
1970-
.then(() => cb(null, undefined))
1993+
.then(result => {
1994+
// In case of race conditions (e.g. two concurrent deletes), or invalid state
1995+
// (e.g. object is already deleted), the result.deletedCount will be 0
1996+
// without error, and we need to catch it because the API might continue and
1997+
// delete the actual data, leading to an invalid state, where MongoDB references
1998+
// and object not in the data layers anymore.
1999+
if (!result || result?.deletedCount != 1) {
2000+
log.debug('internalDeleteObject: object not found or already deleted',
2001+
{ bucket: bucketName, object: key });
2002+
return cb(errors.NoSuchKey);
2003+
}
2004+
return cb(null, undefined);
2005+
})
19712006
.catch(err => {
19722007
log.error('internalDeleteObject: error deleting object',
19732008
{ bucket: bucketName, object: key, error: err.message });
@@ -2030,7 +2065,19 @@ class MongoClientInterface {
20302065
filter: updateDeleteFilter,
20312066
},
20322067
},
2033-
], { ordered: true }).then(() => next(null)).catch(err => next(err)),
2068+
], { ordered: true }).then(result => {
2069+
if (!result || !result.ok) {
2070+
log.debug('internalDeleteObject: bulk operation failed',
2071+
{ bucket: bucketName, object: key });
2072+
return next(errors.InternalError);
2073+
}
2074+
if (result.deletedCount === 0) {
2075+
log.debug('internalDeleteObject: object not deleted',
2076+
{ bucket: bucketName, object: key });
2077+
return next(errors.NoSuchKey);
2078+
}
2079+
return next(null);
2080+
}).catch(err => next(err)),
20342081
], (err, res) => {
20352082
if (err) {
20362083
if (err instanceof ArsenalError && err.is.NoSuchKey) {
@@ -2396,7 +2443,13 @@ class MongoClientInterface {
23962443
i.insertOne(<InfostoreDocument>{
23972444
_id: __UUID,
23982445
value: uuid,
2399-
}, {}).then(() => cb(null)) // FIXME: shoud we check for result.ok === 1 ?
2446+
}, {}).then(result => {
2447+
if (!result || !result.acknowledged) {
2448+
log.debug('writeUUIDIfNotExists: insertion failed');
2449+
return cb(errors.InternalError);
2450+
}
2451+
return cb(null);
2452+
})
24002453
.catch(err => {
24012454
if (err.code === 11000) {
24022455
// duplicate key error
@@ -3124,7 +3177,13 @@ class MongoClientInterface {
31243177
putBucketIndexes(bucketName: string, indexSpecs, log: werelogs.Logger, cb: ArsenalCallback<void>) {
31253178
const c = this.getCollection<ObjectMetastoreDocument>(bucketName);
31263179
const indexes = MongoUtils.indexFormatObjectToMongoArray(indexSpecs);
3127-
c.createIndexes(indexes).then(() => cb(null)).catch(err => {
3180+
c.createIndexes(indexes).then(result => {
3181+
if (!result) {
3182+
log.debug('putBucketIndexes: failed creating bucket indexes');
3183+
return cb(errors.InternalError);
3184+
}
3185+
return cb(null);
3186+
}).catch(err => {
31283187
if (err.codeName === 'NamespaceNotFound') {
31293188
return cb(errors.NoSuchBucket);
31303189
}
@@ -3147,7 +3206,13 @@ class MongoClientInterface {
31473206
deleteBucketIndexes(bucketName: string, indexSpecs: { name: string }[], log: werelogs.Logger, cb: ArsenalCallback<void>) {
31483207
const c = this.getCollection<ObjectMetastoreDocument>(bucketName);
31493208
async.each(indexSpecs,
3150-
(spec, next) => c.dropIndex(spec.name).then(() => next()).catch(err => next(err)),
3209+
(spec, next) => c.dropIndex(spec.name).then(result => {
3210+
if (!result || !result.ok) {
3211+
log.debug('deleteBucketIndexes: failed to drop index', { indexName: spec.name });
3212+
return next(new Error('Failed to drop index'));
3213+
}
3214+
return next();
3215+
}).catch(err => next(err)),
31513216
err => {
31523217
if (err) {
31533218
if (err instanceof MongoServerError && err.codeName === 'NamespaceNotFound') {

lib/storage/metadata/mongoclient/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ function indexFormatMongoArrayToObject(mongoIndexArray: MongoIndex[]): Index[] {
222222
}
223223

224224
function indexFormatObjectToMongoArray(indexObj: Index[]): MongoIndex[] {
225+
if (!indexObj || !Array.isArray(indexObj)) {
226+
return [];
227+
}
228+
225229
return indexObj.map(idx => {
226230
const key = new Map();
227231
idx.keys.forEach(k => key.set(k.key, k.order));

0 commit comments

Comments
 (0)