Evaluate a condition BEFORE put() in NDB and GAE












0















I have a model in my GAE based application, which is being updated quite frequently. And in some cases, it happens that same entity is being updated nearly at the same time. The entity update functionality in the app works like that:




  1. User enters an ID and other properties of the entity which are to be updated.

  2. Retrieve entity from DB against this ID (to make sure ID was valid).

  3. Do bunch of validation on the properties which are going to be updated (e.g. if group_id property is being updated then make sure group is present in DB against this ID and ID is integer.)

  4. After validations, call put() on the entity which was retrieved at step #2.


As, i mentioned same entity can be updated multiple times nearly at the same time, so i came across the classical race condition issue. i.e. let's say 2 update calls were made sequentially, in first call entity was retrieved and validations were in process but, at the same time second call triggered it retrieves the same and updates it properties. The second call also executes put() and update entity in DB. NOTE that first call was not completed yet (due to some time delay), it completes now and calls put() and updates entity in DB.



The end result in DB will be off first update call, but expected result was of second call!



I researched on GAE about this and found pre-put hooks. I think i can use "updated" timestamps to solve this issue i.e. to make sure second call only updates an entity after first call does it. But, i want to use some better approach here e.g. some DB's (like in AWS) provide tags with each DB row and we can ask DB itself to validate this tag before actually putting the record. I am curious as is there any way in GAE to do so. i.e. to ask DB to do conditional put() instead of using pre_put hooks manually?










share|improve this question

























  • Check out transactions in GAE. This is what you need.

    – Jeff O'Neill
    Nov 17 '18 at 13:31











  • @JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

    – HamidArrivy
    Nov 17 '18 at 13:58











  • Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

    – Jeff O'Neill
    Nov 17 '18 at 19:05
















0















I have a model in my GAE based application, which is being updated quite frequently. And in some cases, it happens that same entity is being updated nearly at the same time. The entity update functionality in the app works like that:




  1. User enters an ID and other properties of the entity which are to be updated.

  2. Retrieve entity from DB against this ID (to make sure ID was valid).

  3. Do bunch of validation on the properties which are going to be updated (e.g. if group_id property is being updated then make sure group is present in DB against this ID and ID is integer.)

  4. After validations, call put() on the entity which was retrieved at step #2.


As, i mentioned same entity can be updated multiple times nearly at the same time, so i came across the classical race condition issue. i.e. let's say 2 update calls were made sequentially, in first call entity was retrieved and validations were in process but, at the same time second call triggered it retrieves the same and updates it properties. The second call also executes put() and update entity in DB. NOTE that first call was not completed yet (due to some time delay), it completes now and calls put() and updates entity in DB.



The end result in DB will be off first update call, but expected result was of second call!



I researched on GAE about this and found pre-put hooks. I think i can use "updated" timestamps to solve this issue i.e. to make sure second call only updates an entity after first call does it. But, i want to use some better approach here e.g. some DB's (like in AWS) provide tags with each DB row and we can ask DB itself to validate this tag before actually putting the record. I am curious as is there any way in GAE to do so. i.e. to ask DB to do conditional put() instead of using pre_put hooks manually?










share|improve this question

























  • Check out transactions in GAE. This is what you need.

    – Jeff O'Neill
    Nov 17 '18 at 13:31











  • @JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

    – HamidArrivy
    Nov 17 '18 at 13:58











  • Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

    – Jeff O'Neill
    Nov 17 '18 at 19:05














0












0








0


0






I have a model in my GAE based application, which is being updated quite frequently. And in some cases, it happens that same entity is being updated nearly at the same time. The entity update functionality in the app works like that:




  1. User enters an ID and other properties of the entity which are to be updated.

  2. Retrieve entity from DB against this ID (to make sure ID was valid).

  3. Do bunch of validation on the properties which are going to be updated (e.g. if group_id property is being updated then make sure group is present in DB against this ID and ID is integer.)

  4. After validations, call put() on the entity which was retrieved at step #2.


As, i mentioned same entity can be updated multiple times nearly at the same time, so i came across the classical race condition issue. i.e. let's say 2 update calls were made sequentially, in first call entity was retrieved and validations were in process but, at the same time second call triggered it retrieves the same and updates it properties. The second call also executes put() and update entity in DB. NOTE that first call was not completed yet (due to some time delay), it completes now and calls put() and updates entity in DB.



The end result in DB will be off first update call, but expected result was of second call!



I researched on GAE about this and found pre-put hooks. I think i can use "updated" timestamps to solve this issue i.e. to make sure second call only updates an entity after first call does it. But, i want to use some better approach here e.g. some DB's (like in AWS) provide tags with each DB row and we can ask DB itself to validate this tag before actually putting the record. I am curious as is there any way in GAE to do so. i.e. to ask DB to do conditional put() instead of using pre_put hooks manually?










share|improve this question
















I have a model in my GAE based application, which is being updated quite frequently. And in some cases, it happens that same entity is being updated nearly at the same time. The entity update functionality in the app works like that:




  1. User enters an ID and other properties of the entity which are to be updated.

  2. Retrieve entity from DB against this ID (to make sure ID was valid).

  3. Do bunch of validation on the properties which are going to be updated (e.g. if group_id property is being updated then make sure group is present in DB against this ID and ID is integer.)

  4. After validations, call put() on the entity which was retrieved at step #2.


As, i mentioned same entity can be updated multiple times nearly at the same time, so i came across the classical race condition issue. i.e. let's say 2 update calls were made sequentially, in first call entity was retrieved and validations were in process but, at the same time second call triggered it retrieves the same and updates it properties. The second call also executes put() and update entity in DB. NOTE that first call was not completed yet (due to some time delay), it completes now and calls put() and updates entity in DB.



The end result in DB will be off first update call, but expected result was of second call!



I researched on GAE about this and found pre-put hooks. I think i can use "updated" timestamps to solve this issue i.e. to make sure second call only updates an entity after first call does it. But, i want to use some better approach here e.g. some DB's (like in AWS) provide tags with each DB row and we can ask DB itself to validate this tag before actually putting the record. I am curious as is there any way in GAE to do so. i.e. to ask DB to do conditional put() instead of using pre_put hooks manually?







google-app-engine google-cloud-datastore app-engine-ndb google-app-engine-python






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 '18 at 12:08







HamidArrivy

















asked Nov 17 '18 at 11:07









HamidArrivyHamidArrivy

5219




5219













  • Check out transactions in GAE. This is what you need.

    – Jeff O'Neill
    Nov 17 '18 at 13:31











  • @JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

    – HamidArrivy
    Nov 17 '18 at 13:58











  • Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

    – Jeff O'Neill
    Nov 17 '18 at 19:05



















  • Check out transactions in GAE. This is what you need.

    – Jeff O'Neill
    Nov 17 '18 at 13:31











  • @JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

    – HamidArrivy
    Nov 17 '18 at 13:58











  • Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

    – Jeff O'Neill
    Nov 17 '18 at 19:05

















Check out transactions in GAE. This is what you need.

– Jeff O'Neill
Nov 17 '18 at 13:31





Check out transactions in GAE. This is what you need.

– Jeff O'Neill
Nov 17 '18 at 13:31













@JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

– HamidArrivy
Nov 17 '18 at 13:58





@JeffO'Neill I checked it already and learned that it is using "Optimistic Concurrency Control". You are right, this is what i need. But, transactions has their own limitations which i would like to avoid. That's why i am looking for doing it in a way other than transactions.

– HamidArrivy
Nov 17 '18 at 13:58













Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

– Jeff O'Neill
Nov 17 '18 at 19:05





Maybe use the SQL database instead of datastore. Implementing your own locking mechanism is not an easy thing to do...

– Jeff O'Neill
Nov 17 '18 at 19:05












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
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53350606%2fevaluate-a-condition-before-put-in-ndb-and-gae%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
















draft saved

draft discarded




















































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.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53350606%2fevaluate-a-condition-before-put-in-ndb-and-gae%23new-answer', 'question_page');
}
);

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







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)