Atomicity when updating a field in Collection

When updating a field in collection, as shown in the example of Velo documentation below:

wixData.get("myCollection", "00001")
  .then( (item) => {
    item.last_name = "Smith"; // updated last name
    wixData.update("myCollection", item);
  } )
  .catch( (err) => {
    let errorMsg = err;
  } );

How can I make sure the atomicity of the “get” and “update” in the above code ?

My concern if another session is updating the same collection entry in-between the “get” and “update” above, then the in-between update will be lost. What is the recommended way to avoid this?

UPDATE:

Found similar thread here:

Seems no solution for this issue yet from Wix.

UPDATE:

Found a blog post from Wix-Engineering regarding Optimistic Concurrency Control, which should be able to solve the issue. But I think the technique is not yet possible from Velo.

Query (of course filter the data too), get the filtered result.

If the result item is more than 0, that mean it need update: select the first item

wixData.update(“COLLECTIONID”, {
_id: results.items[0]
//ADD YOUR OWN THING
})

If =0, insert new item

Hi, thanks for the respons. However, my question above is how to avoid data race when two or more sessions trying to update the same entry in the dataset.

For a more concrete example, assume that I have a merchandise dataset with a stock field, showing the number of items that are available for sell. I will try to decrement the field, everytime someone bought an item.

wixData.query("merchandise")
  .eq("name", name)
  .then( (item) => {
    item.stock -= 1;
    wixData.update("merchandise", item);
  })

Now imagine if the above code is called by two sessions (A, B) at the same time. Data race may happen that the stock field is only decrement by one, instead of two, if the code is executed with the following sequence:

(Assume the initial value of stock is 10).

A: query → return item with stock = 10;
B: query → return item with stock = 10;
A: decrement item’s stock → stock = 9;
B: decrement item’s stock → stock = 9;
A: update dataset → dataset item’s stock = 9;
B: update dataset → dataset item’s stock = 9;

When there is no data race, the final stock value will be 8 as expected:

A: query → return item with stock = 10;
A: decrement item’s stock → stock = 9;
A: update dataset → dataset item’s stock = 9;
B: query → return item with stock = 9;
B: decrement item’s stock → stock = 8;
B: update dataset → dataset item’s stock = 8;

The short answer: you can’t. Wix-data knows of no locking, neither optimistic nor pessimistic. The best and most stable you can try to achieve is:

  1. after the .get, create a copy of row content
  2. before updating, .get it again and compare that content with copy
    3)if not equal, warning/error, possible merge
  3. if equal, update

You will always have a “lag” between stage 2 and 4 (couple of millisecs) , can’t be avoided. But …, this will only happen on high volume updates.

Good luck, if you pull it of, let me know, interested.

EDIT: I know wix has experimented with features like transactions and locking, but because of the lag introduced by having to distribute across different copies of db (we are not working all on same db), it introduced a factor 4 increase in response time. Was deemed unacceptable, so they left it. If you really need this, Wix might not be the correct environment for you.

Thanks. At least I can be sure that it’s not possible for the moment. When the data integrity is important, I will need to use third party DB solutions.

Just curious, how did they implement the Wix Stores app then ? If the backend is the same, Wix Stores should also have the same limitations, and may suffer from data race in high volume updates.

@nikobarli " Just curious, how did they implement the Wix Stores app then ? "
You’re not the only one. I asked once, but got a very opaque answer. It would not surprise me if some verticals use another (sql?) db. But, again, I cannot confirm it.