-
Notifications
You must be signed in to change notification settings - Fork 258
fix putData : detect collision on specific provided version id #6230
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
Changes from all commits
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 |
|---|---|---|
|
|
@@ -432,38 +432,26 @@ function putData(request, response, bucketInfo, objMd, log, callback) { | |
| return callback(errorInstances.BadRequest.customizeDescription(errMessage)); | ||
| } | ||
|
|
||
| const incomingVersionIdEncoded = request.headers['x-scal-version-id']; | ||
| if (incomingVersionIdEncoded !== undefined) { | ||
| const incomingVersionIdDecoded = | ||
| incomingVersionIdEncoded !== 'null' ? decode(incomingVersionIdEncoded) : 'null'; | ||
| if (incomingVersionIdDecoded instanceof Error) { | ||
| log.error('crr putData: failed to decode x-scal-version-id header', { | ||
| method: 'putData', | ||
| error: incomingVersionIdDecoded.message, | ||
| }); | ||
| return callback( | ||
| errorInstances.BadRequest.customizeDescription('bad request: invalid x-scal-version-id header'), | ||
| ); | ||
| } | ||
| if (objMd && objMd.versionId === incomingVersionIdDecoded) { | ||
|
Contributor
Author
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. No need for objMd.versionId === incomingVersionIdDecoded anymore as the middleware is already fetching objMd for the specific versionID provided in the header |
||
| // Data already at destination for this version; return 409 with the existing | ||
| // microVersionId so backbeat can decide if putMetadata is still needed. | ||
| log.debug('crr putData: version already at destination', { | ||
| method: 'putData', | ||
| bucketName: request.bucketName, | ||
| objectKey: request.objectKey, | ||
| hasMicroVersionId: !!objMd.microVersionId, | ||
| }); | ||
| request.resume(); | ||
| return _respondWithHeaderCrrConflict( | ||
| response, | ||
| log, | ||
| callback, | ||
| VersionIdCollisionException.name, | ||
| 'version id already at destination', | ||
| objMd.microVersionId, | ||
| ); | ||
| } | ||
| const incomingVersionIdEncoded = request.query?.versionId; | ||
| if (incomingVersionIdEncoded !== undefined && objMd) { | ||
| // objMd is the specific version requested via the versionId query param. | ||
| // Its existence means the data is already at the destination. Return 409 with the | ||
| // existing microVersionId so backbeat can decide if putMetadata is still needed. | ||
| log.debug('crr putData: version already at destination', { | ||
| method: 'putData', | ||
| bucketName: request.bucketName, | ||
| objectKey: request.objectKey, | ||
| hasMicroVersionId: !!objMd.microVersionId, | ||
| }); | ||
| request.resume(); | ||
| return _respondWithHeaderCrrConflict( | ||
| response, | ||
| log, | ||
| callback, | ||
| VersionIdCollisionException.name, | ||
| 'version id already at destination', | ||
| objMd.microVersionId, | ||
| ); | ||
| } | ||
|
|
||
| writeContinue(request, response); | ||
|
|
||
|
Contributor
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. should release cloudserver as well? |
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.
General comment regarding Maël 3 feedbacks : I mostly agree with him that there is weirdness in the code changes, and that the current solution doesn't feel fully satisfying, but I don't think there is any perfect way to do it, else we would need a bigger refactoring
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.
generally : if the proper way requires a refactoring, it should be done. The risk otherwise is to end up with an accumulation of code which is just slightly off - but taken together ends up being a huge pile of mess...
so one must dig into this "not fully satisfying feeling" : is it because we are introducing debt? is that debt something that may come back at us, or something easily manageable? what refactoring would be required? would this refactoring really help the problem here, or just cleanup the rest (but the change would still be as complex)? How long would this refactor take, is it worth it? is it worth it to solve the specific problem at hand? Is it because the problem should be solved more simply? in that case, does the complexity come from the problem it self (i.e. not so easy because of some corner case/...), from some implementation choice, ...? are there some conditions (context) which could allow for a better solution? ...