Bump microVersionId and add isReplica handling#6178
Conversation
Prefer ReplicationInfo.isReplica over replicationInfo.status when producing x-amz-replication-status. The legacy status === 'REPLICA' branch is kept as a fallback so objects written before the feature still surface the correct value. Issue: CLDSRV-906
Bump microVersionId on every user write that changes object metadata other than replicationInfo, providing a unique revision identifier needed by upcoming cascaded CRR loop detection. Issue: CLDSRV-906
When a user updates tags, ACL, retention, or legal-hold on an object that arrived via replication (isReplica=true), the resulting object is no longer a replica - clear the flag so the x-amz-replication-status response header reflects the new state. Issue: CLDSRV-906
Hello maeldonn,My role is to assist you with the merge of this Available options
Available commands
Status report is not available. |
Incorrect fix versionThe
Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:
Please check the |
| "@hapi/joi": "^17.1.1", | ||
| "@smithy/node-http-handler": "^3.0.0", | ||
| "arsenal": "git+https://github.com/scality/Arsenal#8.4.2", | ||
| "arsenal": "git+https://github.com/scality/Arsenal#improvement/ARSN-578/micro-version-id", |
There was a problem hiding this comment.
arsenal is pinned to a branch (improvement/ARSN-578/micro-version-id) instead of a tag. Git-based deps should be pinned to a tag for reproducible builds.
— Claude Code
| const bumpMicroVersionId = require('../../../../../lib/api/apiUtils/object/bumpMicroVersionId'); | ||
|
|
||
| describe('bumpMicroVersionId', () => { | ||
| it('sets a fresh microVersionId when replicationInfo is present', () => { |
There was a problem hiding this comment.
Test names using it() should start with "should".
| it('sets a fresh microVersionId when replicationInfo is present', () => { | |
| it('should set a fresh microVersionId when replicationInfo is present', () => { |
— Claude Code
|
|
||
| afterEach(() => cleanup()); | ||
|
|
||
| it('sets microVersionId on objectPut', async () => { |
There was a problem hiding this comment.
Test names using it() should start with "should".
| it('sets microVersionId on objectPut', async () => { | |
| it('should set microVersionId on objectPut', async () => { |
— Claude Code
|
Codecov Report❌ Patch coverage is Additional details and impacted files
@@ Coverage Diff @@
## development/9.4 #6178 +/- ##
===================================================
- Coverage 85.25% 85.24% -0.02%
===================================================
Files 208 209 +1
Lines 13919 13948 +29
===================================================
+ Hits 11867 11890 +23
- Misses 2052 2058 +6
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
| if (objectMD.replicationInfo?.isReplica) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| objectMD.replicationInfo.isReplica = false; | ||
| } | ||
| const replicationInfo = getReplicationInfo(config, | ||
| objectKey, bucket, true, 0, REPLICATION_ACTION, objectMD); | ||
| if (replicationInfo) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| objectMD.replicationInfo = Object.assign({}, | ||
| objectMD.replicationInfo, replicationInfo); | ||
| } | ||
| bumpMicroVersionId(objectMD); |
There was a problem hiding this comment.
| if (objectMD.replicationInfo?.isReplica) { | |
| // eslint-disable-next-line no-param-reassign | |
| objectMD.replicationInfo.isReplica = false; | |
| } | |
| const replicationInfo = getReplicationInfo(config, | |
| objectKey, bucket, true, 0, REPLICATION_ACTION, objectMD); | |
| if (replicationInfo) { | |
| // eslint-disable-next-line no-param-reassign | |
| objectMD.replicationInfo = Object.assign({}, | |
| objectMD.replicationInfo, replicationInfo); | |
| } | |
| bumpMicroVersionId(objectMD); | |
| const replicationInfo = getReplicationInfo(config, objectKey, bucket, true, 0, REPLICATION_ACTION, objectMD); | |
| if (replicationInfo) { | |
| // eslint-disable-next-line no-param-reassign | |
| objectMD.replicationInfo = Object.assign({}, | |
| objectMD.replicationInfo, replicationInfo); | |
| if (objectMD.replicationInfo?.isReplica) { | |
| // eslint-disable-next-line no-param-reassign | |
| objectMD.replicationInfo.isReplica = false; | |
| } | |
| bumpMicroVersionId(objectMD); | |
| } |
There was a problem hiding this comment.
(same in all files...)
| if (objectMD.replicationInfo?.isReplica) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| objectMD.replicationInfo.isReplica = false; | ||
| } |
There was a problem hiding this comment.
should this not be handled in getReplicationInfo ? (I think this function is not really a getter, but really "builds" the new replication info...)
| const { instanceId, replicationGroupId } = config; | ||
|
|
||
| // eslint-disable-next-line no-param-reassign | ||
| objectMD.microVersionId = versioning.VersionID.generateVersionId(instanceId, replicationGroupId); |
There was a problem hiding this comment.
isn't there a method ObjectMD.updateMicroVersionId() in arsenal ? should it not be used instead?
(if we can't because of POJO, then I wonder if that function was really useful....)
| if (updateMicroVersionId) { | ||
| md.updateMicroVersionId(); | ||
| } | ||
| bumpMicroVersionId(md.getValue(), updateMicroVersionId); |
There was a problem hiding this comment.
- is this not redundant with the other calls in APIs ?
- calling it here we ALWAYS generate a new microVersionId when creating a new object: which is not needed since it comes with a new versionId... (except for non-versioned case, but no replication there: so the function does nothing)
Cloudserver-side prep for cascaded CRR (design): bumps arsenal to the
improvement/ARSN-578/micro-version-idbranch, bumpsmicroVersionIdon every user-facing object metadata write through a singlebumpMicroVersionIdhelper (gated onreplicationInfopresence to keep storage tight, with aforceflag preserving the existing overwriting-version path), sourcesx-amz-replication-statusfrom the newReplicationInfo.isReplicafield with a legacystatus === 'REPLICA'fallback, and clearsisReplicaon direct user writes (tagging / ACL / retention / legal hold) so a modified replica stops looking like one. The backbeat-route side of the design (settingisReplica = trueon incoming replicas, cascade comparison, MultiBackend guard) lands in a follow-up ticket — until then the new fields are read but never set, so observable behavior is unchanged.Issue: CLDSRV-906