0

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?

Community
  • 1
  • 1
Suisse
  • 2,873
  • 4
  • 27
  • 48

2 Answers2

1

I really like sails, however in my googling, I always run across this article about it's shortcomings: https://kev.inburke.com/kevin/dont-use-sails-or-waterline/

Two things mentioned in the article may have relevance to your question:

  1. No support for transactions - preventing race conditions in database updates, etc. You seem to want to hold off a more recent READ operation until a prior WRITE is complete - this is what transactions would provide (but sails waterline doesn't)
  2. 50ms delay on every POST request

I have never investigated the second problem, but maybe it means that post requests received within the same 50ms interval are gathered up and delivered all at once?

arbuthnott
  • 3,669
  • 2
  • 5
  • 18
  • 1
    Hey Arbuth, be careful! This article is from sept 2015, a lot have changed since... Sails was at v0.10 (if im not mistaken) The 50ms complete explanation here: https://github.com/balderdashy/sails/issues/3205 – paulogdm Nov 16 '17 at 01:52
0

This is not a Sails specific question, but how HTTP implements some behaviors. Take a look at these: LINK1, LINK2.

paulogdm
  • 841
  • 7
  • 16
  • "In computing, an idempotent operation is one that has no additional effect if it is called more than once with the same input parameters." - I did the loop with GET each time with different params and it happened the same - So I need a new solution. Thanks – Suisse Nov 15 '17 at 15:12