issue when same function runs simultaneously which cause wrong value to be updated

I’m making a website where users can receive points. Based on these points, a ranking is created.
I have a data hook " afterUpdate" on a collection where the points are entered.

Once one of the records changes, a function ’ calculateScore ’ is called. This function gets the current points of the user by wixData.query() and adds the new ones to it and saves again with wixData.save().

When this function is called one by one (update the points table record by record and waiting some time between the updates) everything runs perfect.

When I update the collection with e few at the same time, the issues starting.

example:
current points: 0

  • record A changes → datahook triggers and calls the updateRanking function. Inside this function, the current amount of points (0) is received via the query(), added with the amount of points (1) and saved again.
  • while this is running, another record is triggered, the current amount that it received is also 0 (did the query before the first one was saved. Adds the amount of points (1) and saves.

The result is a total of 1 point where it had to be 2

import wixData from 'wix-data';

export function calculateScore(item) {
    console.log(item);
 return wixData.query("AnswersDailyBets")
 .eq("matchid", item._id)
 .eq("calculated", null)
 .eq("latestBet", true)
 .or(
            wixData.query("AnswersDailyBets")
 .eq("matchid", item._id)
 .eq("calculated", false)
 .eq("latestBet", true)
 )
 .find().then(res => {
            res.items.forEach(element => {
 let score = element.goalsHome
                console.log(score);
 return wixData.query("UserStand")
 .eq("user", element.user)
 .find().then(result => {
                        console.log(result);
 let temp = result;
                        result.items[0].totaalAantalPunten += parseInt(score)
                        wixData.save("UserStand", result.items[0], { "suppressAuth": true, "suppressHooks": false })
 .then((results) => {
 let item = results; //see item below
                                console.log('after save puntenstand: ', results);
 return results
 })
 })
 })

 return res
 })

}

What is the correct way to solve this? How can I make sure that the second run of this function does not start before this one is done (to make sure that the save is finished)

Hi, your code is not so easy to read as you have some extra unneeded query + you nested the promises instead of chaining them.
For example:
You don’t need the .or() at your first query. All you need there is:

return wixData.query("AnswersDailyBets")
 .eq("matchid", item._id)
 .ne("calculated", true)
 .eq("latestBet", true)
.find()

And as for the nested vs chained, instead of:

return PromiseA
.then(r => {
    PromiseB
        .then(r => {
            PromiseC
                .then(r => {
                //
        })
    })
})

Do:

return PromiseA
.then(r => {
    return PromiseB;
})
.then(r => {
    return PromiseC;
})
.then(r => {
//
})

And then please repost it again.

Hi
thanks a lot for the answer.
I tried to implement your remarks and had some issues with the promise that is returned inside the forEach (by the wixData.query)
So I made the example without the forEach for now because the issue is still the same then (the forEach is to do this for every user but the issue is not when it’s called for different users, it’s only when there are multiple updates to the same user so therefore the forEach is not needed during this example)

When I debug code below, everything looks normal.

But when I click run twice, it’s not working anymore. (this is the same as what will happen as this function is triggered by a datahook of a database so this function will be triggered multiple times in a second

Normally, the first item should add 1 to the total score,
the second run should add 1 to the total score again. Which should result in 2

When I do this one by one, it first adds 1 and during the second run, it’s adding 1 again which results in 2

When I press the run button twice, the end result is 1.

import wixData from 'wix-data';

export function calculateScore(item) {
    console.log("lets calculate")
    console.log(item)
 let score
 return wixData.query("AnswersDailyBets")
 .eq("matchid", item._id)
 .ne("calculated", true)
 .eq("latestBet", true)
 .find()
 .then(r => {
 if (r.items.length > 0) {
                score = r.items[0].goalsHome
                console.log('score: ', score)
 return wixData.query("UserStand")
 .eq("user", r.items[0].user)
 .find()
 } 
 })
 .then( r => {
            console.log("i'm here : ", r)
            r.items[0].totaalAantalPunten += parseInt(score)
 return wixData.save("UserStand", r.items[0], { "suppressAuth": true, "suppressHooks": false })
 })
 .then( r => {
 return r
 })

}