These are chat archives for Automattic/mongoose

5th
Apr 2016
Dmitry Teslitsky
@teslitsky
Apr 05 2016 22:03

Hello everybody.
I need to keep such a data structure in the document:

{
  …
  tickets: [
    {
      user_id: 1,
      from: 1,
      to: 4
    },
    {
      user_id: 2,
      from: 5,
      to: 10
    },
  ],
  last_ticket: 10,
  …
}

User can take multiple tickets with consecutive numbers. I do not know how to ensure atomicity of updating the document with take last_ticket actual value and doing increment from to - from value. Now there may be situations when duplicate from field.
I'm doing something wrong, but I do not know how to fix it.
Grateful for any advice to solve the problem.

LeonineKing1199
@LeonineKing1199
Apr 05 2016 22:07
Unless you're using multiple Node processes, there's no such thing as a race condition is Node.js
Dmitry Teslitsky
@teslitsky
Apr 05 2016 22:21
This message was deleted
LeonineKing1199
@LeonineKing1199
Apr 05 2016 22:22
To speak more, you can't stop different callbacks from being executed in a different order. So if you're running into a problem where order is beginning to matter, it might be easier to re-design your algorithm from a higher perspective so as to avoid creating race conditions in the first place.
Node just basically guarantees that only one set of instructions is interacting with a piece of data at a time. Unless you opt to use multiple Node processes in which case, #AllBetsAreOff
Dmitry Teslitsky
@teslitsky
Apr 05 2016 22:35
Thank you for your answer. I have only one node process, but intense I/O and some actions may have a different exec time, such as the difference in time of document recording. I want to find some pattern to save the sequences in MongoDB.
LeonineKing1199
@LeonineKing1199
Apr 05 2016 22:36
The secret to code that's written in an out-of-order execution is to write code that doesn't care about the data it's operating on, really. I mean, you should check that it's all there and good but once you start doing asynchronous code, it becomes difficult to control the order of execution.
But for your problem, it's actually very easy.
You only want to increment values in a document
This is automatilly free of race conditions, even if you were using multiple Node processes because MongoDB itself is atomic
Let me know if you need help writing the update query
Dmitry Teslitsky
@teslitsky
Apr 05 2016 22:46
Now my code doing following:
  1. Take the current ticket number (10) for the calculation from field
  2. User user_id:3takes tickets from 11 to 17. Tickets are always sequences set. Calculate the increment like to - from + 1 (17-11+1=7)
    ... Another user user_id:4 takes tickets from 11 to 16 and has time to save it to Mongo. Now document looks like
    {
    …
    tickets: [
     {
       user_id: 1,
       from: 1,
       to: 4
     },
     {
       user_id: 2,
       from: 5,
       to: 10
     },
     {
       user_id: 4,
       from: 11,
       to: 17
     },
    ],
    last_ticket: 17,
    …
    }
  3. User 3 save info at this moment
    $addToSet ticket and $inc last_ticket
    {user_id: 3, from: 11, to: 20},
    At this point invalid data are recorded, based on the initial value last_ticket:10, but now last_ticket is 17.
LeonineKing1199
@LeonineKing1199
Apr 05 2016 22:50
Maybe take last_ticket out of the document.
Make it a "global" variable
The problem seems to be that you're reading last_ticket in an asyncrhonous way when what you really want is a synchronous way.
Taking it out of the document should help with that
If you keep last_ticket in the Node.js runtime, all access to it will be serialized and you might get what you were after but I'm not sure. Good tip is, write tests. Write lots and lots of tests.
Dmitry Teslitsky
@teslitsky
Apr 05 2016 22:54
Thank you for a tip. I try it.
LeonineKing1199
@LeonineKing1199
Apr 05 2016 22:56
Yeah, sorry if I'm not more help XD