-
Notifications
You must be signed in to change notification settings - Fork 249
CLDSRV-632 ✨ put metadata edge cases #5913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development/9.1
Are you sure you want to change the base?
Changes from all commits
d6fe9b0
b9b4a83
0745a11
6eef57f
d60fac1
d6480ea
6d6fcb5
f391235
52b06fd
2effafe
51a4101
68abc28
1c32c0b
65452c5
ad98e47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,13 @@ const { listLifecycleOrphanDeleteMarkers } = require('../api/backbeat/listLifecy | |
const { objectDeleteInternal } = require('../api/objectDelete'); | ||
const quotaUtils = require('../api/apiUtils/quotas/quotaUtils'); | ||
const { handleAuthorizationResults } = require('../api/api'); | ||
const { versioningPreprocessing } | ||
= require('../api/apiUtils/object/versioning'); | ||
const {promisify} = require('util'); | ||
|
||
const versioningPreprocessingPromised = promisify(versioningPreprocessing); | ||
metadata.getObjectMDPromised = promisify(metadata.getObjectMD); | ||
metadata.getBucketAndObjectMDPromised = promisify(metadata.getBucketAndObjectMD); | ||
|
||
const { CURRENT_TYPE, NON_CURRENT_TYPE, ORPHAN_DM_TYPE } = constants.lifecycleListing; | ||
|
||
|
@@ -508,23 +515,22 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) { | |
if (err) { | ||
return callback(err); | ||
} | ||
|
||
let omVal; | ||
|
||
try { | ||
omVal = JSON.parse(payload); | ||
} catch { | ||
// FIXME: add error type MalformedJSON | ||
return callback(errors.MalformedPOSTRequest); | ||
} | ||
|
||
const { headers, bucketName, objectKey } = request; | ||
// check if it's metadata only operation | ||
|
||
if (headers['x-scal-replication-content'] === 'METADATA') { | ||
if (!objMd) { | ||
// if the target does not exist, return an error to | ||
// backbeat, who will have to retry the operation as a | ||
// complete replication | ||
return callback(errors.ObjNotFound); | ||
} | ||
// use original data locations and encryption info | ||
|
||
[ | ||
'location', | ||
'x-amz-server-side-encryption', | ||
|
@@ -611,6 +617,12 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) { | |
// To prevent this, the versionId field is only included in options when it is defined. | ||
if (versionId !== undefined) { | ||
options.versionId = versionId; | ||
omVal.versionId = versionId; | ||
|
||
if (isNull) { | ||
omVal.isNull = isNull; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there maybe |
||
} | ||
|
||
// In the MongoDB metadata backend, setting the versionId option leads to the creation | ||
// or update of the version object, the master object is only updated if its versionId | ||
// is the same as the version. This can lead to inconsistencies when replicating objects | ||
|
@@ -641,6 +653,7 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) { | |
if (!request.query?.accountId) { | ||
return next(); | ||
} | ||
|
||
return getCanonicalIdsByAccountId(request.query.accountId, log, (err, res) => { | ||
if (err) { | ||
return next(err); | ||
|
@@ -650,6 +663,36 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) { | |
return next(); | ||
}); | ||
}, | ||
async () => { | ||
if (versioning && !objMd) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when does this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @francoisferrand when you do a PUT on PutMD and the object does not exists. This case can happens when it's an empty object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. still not clear why we need the conditional, and not (more) systematically call versioningPreprocessing. may help to have a comment explaining what use-case this "branch" handles.
do you mean "empty" as in "no data"? I don't understand how it would/should affect the behavior here :-/ |
||
let masterMD; | ||
|
||
try { | ||
masterMD = await metadata.getObjectMDPromised(bucketName, objectKey, {}, log); | ||
} catch (err) { | ||
if (err.is?.NoSuchKey) { | ||
log.debug('no master found for versioned object', { | ||
method: 'putMetadata', | ||
bucketName, | ||
objectKey, | ||
}); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
|
||
if (!masterMD) { | ||
return; | ||
} | ||
|
||
const versioningPreprocessingResult = | ||
await versioningPreprocessingPromised(bucketName, bucketInfo, objectKey, masterMD, log); | ||
|
||
if (versioningPreprocessingResult?.nullVersionId) { | ||
omVal.nullVersionId = versioningPreprocessingResult.nullVersionId; | ||
} | ||
Comment on lines
+691
to
+693
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in other uses of versioningPreprocessing (in putObject / copyObject / putMpu) we set multiple (and different) fields:
this gets translated (in
→ so it seems many more fields may be set, to cover all cases? |
||
} | ||
}, | ||
next => { | ||
log.trace('putting object version', { | ||
objectKey: request.objectKey, omVal, options }); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the semantics of putObject in metadata layer (either backends, i.e. metadata or mongodbClientInterface) are not clear or precisely defined : does setting this not interract (in some weird or unacceptable way?) the behavior of the
versionId
option?