Prevent concurrent changes to same entity from different submissions #1195
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds a solution for the race condition described in getodk/central#705.
What has been done to verify that this works as intended?
I'm able to reproduce the race condition in testing. However, I'm still working on writing a test that feels sufficiently reliable and not like its own race condition. After this PR is merged, I'll follow up with another PR that adds a test.
Why is this the best possible solution? Were any other approaches considered?
I wanted to reuse the
_lockEntity()
function, which I think was introduced in #1033. I had to make one change to the function in this PR: see the code comments in the diff.There was a little bit of a question of timing: when exactly should the entity be locked? I decided to lock the entity in the main body of
Entities._processSubmissionEvent()
and not inEntities._createEntity()
orEntities._updateEntity()
, even though there are cases where the latter two functions return early and never read or write to the entity. I decided to take that approach because it's possible for bothEntities._createEntity()
andEntities._updateEntity()
to be run: if bothcreate="true"
andupdate="true"
are specified, thenEntities._createEntity()
will be attempted ifEntities._updateEntity()
fails. I wanted to avoid a situation where multiple locks were attempted on the same entity.Before submitting this PR, please make sure you have:
make test
and confirmed all checks still pass OR confirm CircleCI build passes