refactor/submit-form: reduce possibility of race conditions in submission flow #1045
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.
Problem
Addresses #1044
Solution
I did not manage to reproduce the bug in question. This is not a surprise as concurrency bugs are indeterministic by definition. However, based on the symptom and rarity of the bug, it is possible that the behavior is a result of edge cases caused by poor integration with AngularJS. Multiple code paths were thoroughly examined, and the appropriate refactor performed to improve code clarity and reduce the likelihood of bugs.
The
controllerState
variable is used to store the cloned form object in thesavedForm
property before fields were locked/disabled. It was previously not attached to the directive scope, but simply as aconst
which makes it a possible candidate to resolve the concurrency bug as AngularJS would not be tracking changes to this variable during the digest cycle.The need to clone the form object before calling this function was removed by refactoring to avoid assigning to the
form.attachment
property (it is a very bad practice to mutate function arguments). This not only removed the need for an expensive clone operation, but also guarantees that there can be no divergence between the form object in the controller scope vs the one used in thesubmitForm
function, since the call tosubmitForm(scope.form)
is a reference to the same form object.Almost all the logic necessary to generate the POST body has also been moved into the
Form
class as instance methods, with the exception of captcha. Internal methods have also been prefixed with an underscore to discourage external use.Improvements:
Bug Fixes:
Tests
Manually tested with storage mode submissions with and without attachment fields. As this is sensitive code with low test coverage, the reviewer is invited to step through the commits to verify that the new implementation is sound.