-
Notifications
You must be signed in to change notification settings - Fork 76
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
Mark soft conflict if not contiguous with trunk #1187
Changes from 3 commits
8b50747
21a580d
f4d54fc
9dd9db0
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 |
---|---|---|
|
@@ -1343,6 +1343,236 @@ describe('Offline Entities', () => { | |
}); | ||
}); | ||
|
||
describe('conflict cases', () => { | ||
it('should mark an update that is not contiguous with its trunk version as a soft conflict', testOfflineEntities(async (service, container) => { | ||
const asAlice = await service.login('alice'); | ||
const branchId = uuid(); | ||
|
||
// Update existing entity on server (change age from 22 to 24) | ||
await asAlice.patch('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc?baseVersion=1') | ||
.send({ data: { age: '24' } }) | ||
.expect(200); | ||
|
||
// Send update (change status from null to arrived) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
|
||
// Send second update (change age from 22 to 26) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('one', 'one-update2') | ||
.replace('baseVersion="1"', 'baseVersion="2"') | ||
.replace('<status>arrived</status>', '<age>26</age>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
|
||
await exhaust(container); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc/versions') | ||
.then(({ body: versions }) => { | ||
versions.map(v => v.conflict).should.eql([null, null, 'soft', 'soft']); | ||
}); | ||
})); | ||
|
||
it('should mark an update that is not contiguous (due to force processing) as a soft conflict', testOfflineEntities(async (service, container) => { | ||
const asAlice = await service.login('alice'); | ||
const branchId = uuid(); | ||
|
||
// Send second update first | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('one', 'one-update2') | ||
.replace('baseVersion="1"', 'baseVersion="2"') | ||
.replace('<status>arrived</status>', '<status>checked in</status>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
|
||
await exhaust(container); | ||
await container.Entities.processBacklog(true); | ||
|
||
// Send first update now (it will be applied right away) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
|
||
await exhaust(container); | ||
|
||
// Send fourth update | ||
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. fourth update from the branch (3rd update is missing). this will get held in the backlog and when it gets force-processed, it will take the latest version as the base version and therefore not have a conflict due to version mismatch... 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. link to issue here and mention the scenario is mentioned there |
||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('one', 'one-update4') | ||
.replace('baseVersion="1"', 'baseVersion="4"') | ||
.replace('<status>arrived</status>', '<status>departed</status>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
|
||
await exhaust(container); | ||
await container.Entities.processBacklog(true); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc/versions') | ||
.then(({ body: versions }) => { | ||
versions.map(v => v.conflict).should.eql([null, null, 'hard', 'soft']); | ||
}); | ||
})); | ||
|
||
it('should mark an update that is not contiguous with its trunk version as a soft conflict on entity despite earlier conflict resolution', testOfflineEntities(async (service, container) => { | ||
const asAlice = await service.login('alice'); | ||
const branchId = uuid(); | ||
|
||
// Update existing entity on server (change age from 22 to 24) | ||
await asAlice.patch('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc?baseVersion=1') | ||
.send({ data: { age: '24' } }) | ||
.expect(200); | ||
|
||
// Send update (change status from null to arrived) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
await asAlice.patch('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc?resolve=true&baseVersion=3') | ||
.expect(200); | ||
|
||
// Send second update (change age from 22 to 26) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.one | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('one', 'one-update2') | ||
.replace('baseVersion="1"', 'baseVersion="2"') | ||
.replace('<status>arrived</status>', '<age>26</age>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc/versions') | ||
.then(({ body: versions }) => { | ||
versions.map(v => v.conflict).should.eql([null, null, 'soft', 'soft']); | ||
}); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789abc') | ||
.then(({ body: entity }) => { | ||
should(entity.conflict).equal('soft'); | ||
}); | ||
})); | ||
|
||
it('should mark an update that is not contiguous (from an offline create branch) as a soft conflict on entity despite earlier conflict resolution', testOfflineEntities(async (service, container) => { | ||
const asAlice = await service.login('alice'); | ||
const branchId = uuid(); | ||
|
||
// Send initial submission to create entity | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.two) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
// Update existing entity on server before getting the rest of the branch | ||
await asAlice.patch('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd?baseVersion=1') | ||
.send({ data: { age: '24' } }) | ||
.expect(200); | ||
|
||
// Send update (change status from new to arrived) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.two | ||
.replace('two', 'two-update1') | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('create="1"', 'update="1"') | ||
.replace('baseVersion=""', 'baseVersion="1"') | ||
.replace('<status>new</status>', '<status>arrived</status>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
// Conflict is hard here | ||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd') | ||
.then(({ body: entity }) => { | ||
should(entity.conflict).equal('hard'); | ||
}); | ||
|
||
// resolve the conflict | ||
await asAlice.patch('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd?resolve=true&baseVersion=3') | ||
.expect(200); | ||
|
||
// Send second update in offline create-update-update chain (change age from 22 to 26) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.two | ||
.replace('two', 'two-update2') | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('create="1"', 'update="1"') | ||
.replace('baseVersion=""', 'baseVersion="2"') | ||
.replace('<status>new</status>', '<status>arrived</status>') | ||
.replace('<age>20</age>', '<age>27</age>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd/versions') | ||
.then(({ body: versions }) => { | ||
versions.map(v => v.conflict).should.eql([null, null, 'hard', 'soft']); | ||
}); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd') | ||
.then(({ body: entity }) => { | ||
should(entity.conflict).equal('soft'); | ||
}); | ||
})); | ||
|
||
it('should check that interrupting version logic is doesnt flag non-conflicts as conflicts', testOfflineEntities(async (service, container) => { | ||
const asAlice = await service.login('alice'); | ||
const branchId = uuid(); | ||
|
||
// Send initial submission to create entity | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.two) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
// Send second update in offline create-update-update chain (change age from 22 to 26) | ||
await asAlice.post('/v1/projects/1/forms/offlineEntity/submissions') | ||
.send(testData.instances.offlineEntity.two | ||
.replace('two', 'two-update') | ||
.replace('branchId=""', `branchId="${branchId}"`) | ||
.replace('create="1"', 'update="1"') | ||
.replace('baseVersion=""', 'baseVersion="1"') | ||
.replace('<status>new</status>', '<status>arrived</status>') | ||
.replace('<age>20</age>', '<age>27</age>') | ||
) | ||
.set('Content-Type', 'application/xml') | ||
.expect(200); | ||
await exhaust(container); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd/versions') | ||
.then(({ body: versions }) => { | ||
versions.map(v => v.conflict).should.eql([null, null]); | ||
}); | ||
|
||
await asAlice.get('/v1/projects/1/datasets/people/entities/12345678-1234-4123-8234-123456789ddd') | ||
.then(({ body: entity }) => { | ||
should(entity.conflict).equal(null); | ||
}); | ||
})); | ||
}); | ||
|
||
describe('locking an entity while processing a related submission', function() { | ||
this.timeout(8000); | ||
|
||
|
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.
We saw a scenario in a test where this logic didn't quite work out