Er. Mohit Agrawal
Er. Mohit Agrawal

Reputation: 2276

Concurrent request handling in Nodejs

I have a issue of concurrent request, which modifies db.

What am I doing is. One request fetch data for user-1 , then calculate data for user-1 modified a field-1 in record, and save.

next request fetch data for user-1 , then calculate data for user-1 modified a field-1 in record, and save.

Both request operates simultaneously. so last request update the wrong data.

function calculate() {
  var needUpdate = false;
  user = new UserLib(user_id);
  var old_config = user.config;
  if (old_config[req.id]) {
    old_config[req.id].value = 0;
    needUpdate = true;
  }
  if (req.delete == void(0) || req.delete == false) {
    delete req.delete;
    old_config[req.id].value = old_config[req.id].value + 1;
    needUpdate = true;
  }
  if (needUpdate) {
    return user.save();
  }
  return true;
}

enter image description here

We are getting both requests at the same time.

  var express = require('express');
var app = express();

app.get('/update', function(req, res) {

  res.writeHead(200, {
    'Content-Type': 'text/html'
  });


  calculate(req);

  function calculate(req) {

    var needUpdate = false;

    user = new UserLib(user_id);
    var old_config = user.config;

    if (old_config[req.id]) {
      old_config[req.id].value = 0;
      needUpdate = true;
    }

    if (req.delete == void(0) || req.delete == false) {
      delete req.delete;
      old_config[req.id].value = old_config[req.id].value + 1;
      needUpdate = true;
    }

    if (needUpdate) {
      user.save();
    }
  }

  res.end('Done');
});
first reuest with following parameter {
  user_id: 1,
  id: 1,
  value: 5,
  delete: false
}

Anothere request with follwing parmter {
  user_id: 1,
  id: 1,
  delete: true
}

Upvotes: 1

Views: 201

Answers (1)

soyuka
soyuka

Reputation: 9105

If you want to operate on each request simultaneously, I'd suggest to use Bluebird.map where you can handle each request as you want, with concurrency, and a final result.

For example:

let users = ['foo', 'bar']; //fetching users you want

Bluebird.map(users, (user) => {
   return user.calculate()
   .then((res) => res.shouldUpdate ? user.save() : Promise.resolve())
}, {concurrency: 2})
.then((results) => {
  //results is an array with both resolved promises from below
})

You may also be interested in Bluebird.join where you could calculate, and join the resulting data for more than one promise.

Second example where you fetch same user twice in the same promise:

//both are promises
Bluebird.all([fetchUser1, fetchUser2])
.spread(function(user1, user2) {
   //check if should update
   return user1.delete !== user2.delete ? user.delete() : null
})
.then(() => {})

Bluebird.spread documentation

Upvotes: 1

Related Questions