How to prevent race condition when creating a document on parse server?
A mobile app uses parse server as a backend with mongoDB
as database.
For every user in the User
collection there is a user profile in the UserProfile
collection. A user profile has a pointer field as a reference to the User
to which the user profile belongs.
The problem is that multiple user profiles are created for the same user during sign up.
That is because the sign-up process looks like this:
Client: user signs up
Server: creates user profile inafterSave
ofUser
Client: after sign-up calls cloud code functionupdateProfile
to update information in the user profile
Server:updateProfile
looks for existing user profile or creates a new one if none exists
This causes a race condition: The server creates a user profile in step #2 and at the same time updateProfile
creates a new user profile in step #4. The time difference in createdAt
of these user profiles is milliseconds.
Now:
If I leave out step #2, then even if step #4 gets calls multiple times immediately after each other, it can cause a race condition because
updateProfile
won't find a user profile until it's created. On the other hand every user needs to have a user profile associated with it, so creating it server side is the only way to ensure that.If I change step #4, to not create a new profile, then the information in the profile is not updated when the client calls the cloud code function
updateProfile
because the user profile from step #1 is not yet created.
What is the correct approach?
Update:
- Unfortunately the user profile cannot be created on
beforeSave
of theUser
because it doesn't seem to have anID
yet. If that was possible then it would be ensured that a user profile is created before the client callsupdateProfile
.
mongodb parse.com parse-server
|
show 1 more comment
A mobile app uses parse server as a backend with mongoDB
as database.
For every user in the User
collection there is a user profile in the UserProfile
collection. A user profile has a pointer field as a reference to the User
to which the user profile belongs.
The problem is that multiple user profiles are created for the same user during sign up.
That is because the sign-up process looks like this:
Client: user signs up
Server: creates user profile inafterSave
ofUser
Client: after sign-up calls cloud code functionupdateProfile
to update information in the user profile
Server:updateProfile
looks for existing user profile or creates a new one if none exists
This causes a race condition: The server creates a user profile in step #2 and at the same time updateProfile
creates a new user profile in step #4. The time difference in createdAt
of these user profiles is milliseconds.
Now:
If I leave out step #2, then even if step #4 gets calls multiple times immediately after each other, it can cause a race condition because
updateProfile
won't find a user profile until it's created. On the other hand every user needs to have a user profile associated with it, so creating it server side is the only way to ensure that.If I change step #4, to not create a new profile, then the information in the profile is not updated when the client calls the cloud code function
updateProfile
because the user profile from step #1 is not yet created.
What is the correct approach?
Update:
- Unfortunately the user profile cannot be created on
beforeSave
of theUser
because it doesn't seem to have anID
yet. If that was possible then it would be ensured that a user profile is created before the client callsupdateProfile
.
mongodb parse.com parse-server
1
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
1
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
@danh (a)afterSave
hook forUser
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.
– Manuel
Nov 18 '18 at 16:51
|
show 1 more comment
A mobile app uses parse server as a backend with mongoDB
as database.
For every user in the User
collection there is a user profile in the UserProfile
collection. A user profile has a pointer field as a reference to the User
to which the user profile belongs.
The problem is that multiple user profiles are created for the same user during sign up.
That is because the sign-up process looks like this:
Client: user signs up
Server: creates user profile inafterSave
ofUser
Client: after sign-up calls cloud code functionupdateProfile
to update information in the user profile
Server:updateProfile
looks for existing user profile or creates a new one if none exists
This causes a race condition: The server creates a user profile in step #2 and at the same time updateProfile
creates a new user profile in step #4. The time difference in createdAt
of these user profiles is milliseconds.
Now:
If I leave out step #2, then even if step #4 gets calls multiple times immediately after each other, it can cause a race condition because
updateProfile
won't find a user profile until it's created. On the other hand every user needs to have a user profile associated with it, so creating it server side is the only way to ensure that.If I change step #4, to not create a new profile, then the information in the profile is not updated when the client calls the cloud code function
updateProfile
because the user profile from step #1 is not yet created.
What is the correct approach?
Update:
- Unfortunately the user profile cannot be created on
beforeSave
of theUser
because it doesn't seem to have anID
yet. If that was possible then it would be ensured that a user profile is created before the client callsupdateProfile
.
mongodb parse.com parse-server
A mobile app uses parse server as a backend with mongoDB
as database.
For every user in the User
collection there is a user profile in the UserProfile
collection. A user profile has a pointer field as a reference to the User
to which the user profile belongs.
The problem is that multiple user profiles are created for the same user during sign up.
That is because the sign-up process looks like this:
Client: user signs up
Server: creates user profile inafterSave
ofUser
Client: after sign-up calls cloud code functionupdateProfile
to update information in the user profile
Server:updateProfile
looks for existing user profile or creates a new one if none exists
This causes a race condition: The server creates a user profile in step #2 and at the same time updateProfile
creates a new user profile in step #4. The time difference in createdAt
of these user profiles is milliseconds.
Now:
If I leave out step #2, then even if step #4 gets calls multiple times immediately after each other, it can cause a race condition because
updateProfile
won't find a user profile until it's created. On the other hand every user needs to have a user profile associated with it, so creating it server side is the only way to ensure that.If I change step #4, to not create a new profile, then the information in the profile is not updated when the client calls the cloud code function
updateProfile
because the user profile from step #1 is not yet created.
What is the correct approach?
Update:
- Unfortunately the user profile cannot be created on
beforeSave
of theUser
because it doesn't seem to have anID
yet. If that was possible then it would be ensured that a user profile is created before the client callsupdateProfile
.
mongodb parse.com parse-server
mongodb parse.com parse-server
edited Nov 15 '18 at 14:18
Manuel
asked Nov 15 '18 at 14:06
ManuelManuel
5,79712050
5,79712050
1
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
1
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
@danh (a)afterSave
hook forUser
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.
– Manuel
Nov 18 '18 at 16:51
|
show 1 more comment
1
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
1
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
@danh (a)afterSave
hook forUser
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.
– Manuel
Nov 18 '18 at 16:51
1
1
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
1
1
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
@danh (a)
afterSave
hook for User
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.– Manuel
Nov 18 '18 at 16:51
@danh (a)
afterSave
hook for User
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.– Manuel
Nov 18 '18 at 16:51
|
show 1 more comment
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53321248%2fhow-to-prevent-race-condition-when-creating-a-document-on-parse-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53321248%2fhow-to-prevent-race-condition-when-creating-a-document-on-parse-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Does the UserProfile have a pointer to User? If so, you can make a unique index on that field.
– Arthur Cinader
Nov 16 '18 at 2:27
I thought of that, it prevents multiple user profiles. However, step #4 will still fail because it won't find the user profile that hasn't been created by step #2 yet. I need something that ensures that the write operation in step #2 is done before the find/modify operation in step #4.
– Manuel
Nov 16 '18 at 2:32
so why even bother doing #2? why not count on #4 to do the work. but you should make the unique index anyway.
– Arthur Cinader
Nov 16 '18 at 2:37
1
Please show your code. What you're trying to do is easily done without race conditions. In a nutshell, (a) you can have your afterSave hook create and update the profile and skip step #4, or (b) skip step #2, and after user creation is complete call updateProfile (which will do a create first if there is none). If one or both of those approaches is failing, then the code requires review.
– danh
Nov 17 '18 at 23:43
@danh (a)
afterSave
hook forUser
class cannot update the user profile because the information to update is provided by the client in step #4, so step #4 cannot be skipped. (b) if step #2 is skipped, then the creation of a user profile is determined by the client. If a client is terminated after the user creation request and before the response (e.g. on slow network), then no user profile will be created. No code to review here, this is a conceptual question.– Manuel
Nov 18 '18 at 16:51