Skip to content

Commit 6387296

Browse files
committed
✨ add a new condition "$exists: false" in repairMaster option to manage
the case when the versionId does not exists Issue: ARSN-515
1 parent 4432117 commit 6387296

File tree

2 files changed

+88
-9
lines changed

2 files changed

+88
-9
lines changed

lib/storage/metadata/mongoclient/MongoClientInterface.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,8 +1143,9 @@ class MongoClientInterface {
11431143
const ops: AnyBulkWriteOperation<ObjectMetastoreDocument>[] = [];
11441144
// filter to get master
11451145
const filter = {
1146-
'_id': masterKey,
1147-
'value.versionId': {
1146+
_id: masterKey,
1147+
$or: [
1148+
{ 'value.versionId': { $exists: false } },
11481149
// We break the semantic correctness here with
11491150
// $gte instead of $gt because we do not have
11501151
// a microVersionId to capture the micro
@@ -1155,8 +1156,11 @@ class MongoClientInterface {
11551156
// replication and ingestion can hopefully
11561157
// ensure), but this would not work e.g. in
11571158
// the case of an active-active replication.
1158-
$gte: mstObjVal!.versionId,
1159-
},
1159+
1160+
{ 'value.versionId': {
1161+
$gte: mstObjVal!.versionId,
1162+
} },
1163+
]
11601164
};
11611165
// values to update master
11621166
const update = {

tests/unit/storage/metadata/mongoclient/MongoClientInterface.spec.js

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const MongoUtils = require('../../../../../lib/storage/metadata/mongoclient/util
1414
const ObjectMD = require('../../../../../lib/models/ObjectMD').default;
1515
const { BucketVersioningKeyFormat } = require('../../../../../lib/versioning/constants').VersioningConstants;
1616
const { formatMasterKey } = require('../../../../../lib/storage/metadata/mongoclient/utils');
17+
const { promisify } = require('util');
1718

1819
const dbName = 'metadata';
1920
const baseBucket = BucketInfo.fromObj({
@@ -716,15 +717,27 @@ describe('MongoClientInterface, tests', () => {
716717
assert.ok(retrievedCapacityInfo, 'VeeamSOSApi.CapacityInfo should exist');
717718

718719
assert.strictEqual(typeof retrievedCapacityInfo.Capacity, 'bigint', 'Capacity should be a bigint');
719-
assert.strictEqual(retrievedCapacityInfo.Capacity.toString(), veeamCapacity.Capacity, 'Capacity value mismatch');
720+
assert.strictEqual(
721+
retrievedCapacityInfo.Capacity.toString(),
722+
veeamCapacity.Capacity,
723+
'Capacity value mismatch',
724+
);
720725

721726
assert.strictEqual(typeof retrievedCapacityInfo.Available, 'bigint', 'Available should be a bigint');
722-
assert.strictEqual(retrievedCapacityInfo.Available.toString(), veeamCapacity.Available, 'Available value mismatch');
727+
assert.strictEqual(
728+
retrievedCapacityInfo.Available.toString(),
729+
veeamCapacity.Available,
730+
'Available value mismatch',
731+
);
723732

724733
assert.strictEqual(typeof retrievedCapacityInfo.Used, 'bigint', 'Used should be a bigint');
725734
assert.strictEqual(retrievedCapacityInfo.Used.toString(), veeamCapacity.Used, 'Used value mismatch');
726735

727-
assert.strictEqual(retrievedCapacityInfo.LastModified, veeamCapacity.LastModified, 'LastModified value mismatch');
736+
assert.strictEqual(
737+
retrievedCapacityInfo.LastModified,
738+
veeamCapacity.LastModified,
739+
'LastModified value mismatch',
740+
);
728741
done();
729742
});
730743
});
@@ -895,6 +908,9 @@ describe('MongoClientInterface, putObjectVerCase4', () => {
895908
if (err) {
896909
return done(err);
897910
}
911+
912+
client.putObjectVerCase4Promised = promisify(client.putObjectVerCase4).bind(client);
913+
898914
return createBucket(client, bucketName, true, err => {
899915
if (err) {
900916
return done(err);
@@ -1102,6 +1118,65 @@ describe('MongoClientInterface, putObjectVerCase4', () => {
11021118
},
11031119
);
11041120
});
1121+
1122+
it('should handle missing versionId ($exists: false) in putObjectVerCase4 to update master', async () => {
1123+
const objName = 'test-object';
1124+
const versionId = 'test-version-id';
1125+
const objMD = new ObjectMD()
1126+
.setKey(objName)
1127+
.setDataStoreName('us-east-1')
1128+
.setContentLength(100)
1129+
.setLastModified(new Date());
1130+
1131+
const updateOneStub = sandbox.stub(collection, 'updateOne').resolves({ modifiedCount: 1 });
1132+
1133+
sandbox.stub(client, 'getLatestVersion').callsFake((c, objName, vFormat, log, cb) => {
1134+
cb(null, objMD.getValue());
1135+
});
1136+
1137+
const bulkWriteStub = sandbox.stub(collection, 'bulkWrite').resolves({
1138+
modifiedCount: 1,
1139+
upsertedCount: 1,
1140+
matchedCount: 1,
1141+
});
1142+
1143+
const params = {
1144+
vFormat: BucketVersioningKeyFormat.v1,
1145+
versionId,
1146+
repairMaster: true,
1147+
versioning: true,
1148+
needOplogUpdate: false,
1149+
originOp: 'test',
1150+
conditions: {},
1151+
};
1152+
1153+
const result = await client.putObjectVerCase4Promised(
1154+
collection,
1155+
bucketName,
1156+
objName,
1157+
objMD.getValue(),
1158+
params,
1159+
logger,
1160+
);
1161+
1162+
assert(result, 'Expected result on success');
1163+
assert.strictEqual(
1164+
result,
1165+
`{"versionId": "undefined"}`,
1166+
'Expected versionId in result',
1167+
);
1168+
assert(updateOneStub.calledOnce, 'Expected updateOne to be called');
1169+
assert(bulkWriteStub.calledOnce, 'Expected bulkWrite to be called');
1170+
const bulkOps = bulkWriteStub.firstCall.args[0];
1171+
const masterUpdateOp = bulkOps.find(
1172+
op => op.updateOne && op.updateOne.filter._id === formatMasterKey(objName, BucketVersioningKeyFormat.v1)
1173+
);
1174+
assert(masterUpdateOp, 'Expected master update operation');
1175+
assert(
1176+
masterUpdateOp.updateOne.filter.$or[0]['value.versionId'].$exists === false,
1177+
'Expected filter to check for non-existing versionId'
1178+
);
1179+
});
11051180
});
11061181

11071182
describe('MongoClientInterface, putObjectNoVer', () => {
@@ -1470,7 +1545,7 @@ describe('MongoClientInterface, writeUUIDIfNotExists', () => {
14701545

14711546
sandbox.stub(client, 'getCollection').returns(mockCollection);
14721547

1473-
client.writeUUIDIfNotExists('test-uuid', logger, (err) => {
1548+
client.writeUUIDIfNotExists('test-uuid', logger, err => {
14741549
try {
14751550
assert(err, 'Expected an error to be returned');
14761551
assert.strictEqual(err.code, 500, 'Expected 500 error code');
@@ -1491,7 +1566,7 @@ describe('MongoClientInterface, writeUUIDIfNotExists', () => {
14911566

14921567
sandbox.stub(client, 'getCollection').returns(mockCollection);
14931568

1494-
client.writeUUIDIfNotExists('test-uuid', logger, (err) => {
1569+
client.writeUUIDIfNotExists('test-uuid', logger, err => {
14951570
try {
14961571
assert(err, 'Expected an error to be returned');
14971572
assert.strictEqual(err.code, 409, 'Expected KeyAlreadyExists error');

0 commit comments

Comments
 (0)