NULLchimp
NULLchimp

Reputation: 775

MongoDB: findOneAndUpdate seems to be not atomic

I am using nodejs + mongodb as a backend for a largely distributed web application. I have a series of events, that need to be in a specific order. There are multiple services generating these events and my application should process and store them as they come in and at any given time I want to have them in the correct order.

I cannot rely on timestamps since javascript only provides timestamps in milliseconds, which is not accurate enough for my case.

I have two collections in my database. One that stores the events and one that stores an index, which represents my eventorder. I have tried using findOneAndUpdate in order to increase my index atomically. This however does not seem to be working.

console.log('Adding');
console.log(event.type);

this._db.collection('evtidx').findOneAndUpdate({ id : 'index' }, { $inc: { value : 1 } }, (err, res) => {
    console.log('For '+event.type);
    console.log('Got value: '+res.value.value);

    event.index = res.value.value;
    this._db.collection('events').insertOne(event, (err, evtres) => {
        if (err) {
            throw err;
        }
    });
});

When I check the output of the code above I see:

Adding Event1
Adding Event2
Adding Event3
Adding Event4
For Event1 Got value: 1
For Event3 Got value: 4
For Event2 Got value: 2
For Event4 Got value: 3

Which concludes to me, that my code is not working atomically. The events come in in the correct index, but don't have the correct order attached to them after findOneAndUpdate. Could anyone help me out there?

Upvotes: 0

Views: 1266

Answers (1)

kailniris
kailniris

Reputation: 9516

Atomic database operations does not mean that they lock the database while the request is running. Maybe You are getting requests in order but they are not executed in sequential order nor in the backend nor in the database.
What you need to do is read the last document index from the 'events' collection. If its one less then your current request index then insert else wait and retry.
Although this can cause problems if one event fails because of network error or something else. Then Your request processing would stop.

Upvotes: 1

Related Questions