I noticed something in my Sails.js App which I can't explain:
The Client sends a GET request to the UserController, the UserController creates a new record in the TransactionTable for this User if its account is greater than 0 and updates its account to 0:
User.findOne(currentUser.id, function foundUser(err, foundUser) {
if(foundUser.account > 0){
//update the foundUsers account to 0
User.update(foundUser.id, {account:0}, function updateUser(err, updatedUser) {
//if error rollback;
//save the User to the Transactions Table:
Transactions.create(foundUser, function(){
//if error rollback;
return res.json("You will get Money!");
})
})
}else{
return res.json("Sorry you don't have enough Coins");
}
})
I did a loop(5repeats) on the Clientside for the GET request and it created only 1 Transaction and the other 4 got the log that foundUser.account is 0. So the output was:
You will get Money!
Sorry you don't have enough Coins
Sorry you don't have enough Coins
Sorry you don't have enough Coins
Sorry you don't have enough Coins
I did the same loop with POST and it created 5 Transactions in the Table.
You will get Money!
You will get Money!
You will get Money!
You will get Money!
You will get Money!
So: Is GET atomic and POST not in a Sail.js Application? And is this way safe for production?
Edit: GET request is idempotent - I tested the same loop with GET but this time I added a different value for each request for an argument and got 5 Transactions.
You will get Money!
You will get Money!
You will get Money!
You will get Money!
You will get Money!
How does this idempotent work? It has nothing to do with caching right? Because when it would just cache the response for the already known request like in the first GET example, the first example would also return 5 times the same response? But it actually "change" the resource on the server and delivers different responses. strange.
How can I fix this problem? So that in the time one transaction is written no other client can make a request?