Skip to content
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

refactor/submit-form: reduce possibility of race conditions in submission flow #1045

Merged
merged 7 commits into from
Jan 26, 2021

Conversation

liangyuanruo
Copy link
Contributor

@liangyuanruo liangyuanruo commented Jan 25, 2021

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.

  1. controllerState variable refactor

The controllerState variable is used to store the cloned form object in the savedForm property before fields were locked/disabled. It was previously not attached to the directive scope, but simply as a const 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.

  1. submitFormMain function refactor

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 the submitForm function, since the call to submitForm(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:

  • Improved code cleanliness and efficiency

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.

Copy link
Contributor

@mantariksh mantariksh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@@ -1,3 +1,6 @@
const _ = require('lodash')
const formsg = require('@opengovsg/formsg-sdk')()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are initialising the SDK in production mode here, even if the code is running in dev/staging. this works fine for now because the SDK's crypto.encrypt function does not depend on FormSG's public key, but may lead to unexpected behaviour in future if this class has to call other SDK methods.

@liangyuanruo liangyuanruo merged commit 640b6ed into develop Jan 26, 2021
@liangyuanruo liangyuanruo deleted the refactor/submit-form branch January 26, 2021 03:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Possible concurrency bug causing empty values in Storage Mode submissions
2 participants