1

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
}

9
  • What library are you using to control flows? Promises or async? Commented May 25, 2016 at 9:41
  • We are using bluebird Commented May 25, 2016 at 9:43
  • Actually this is something that can not be handle by promisification i think. if you have any solution regarding this, it will be appreciating. Commented May 25, 2016 at 9:45
  • Wrong, everything can be handled through promisification. Could you give me a piece of code to work with? I'm writing a general answer for now. Commented May 25, 2016 at 9:46
  • 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; } Commented May 25, 2016 at 9:56

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

Actually function is to update a user's data based on previous state. let's say all happens promisified, first fetch then update then return. But point is that both server request are independent, that have nothing to do with promisification.
I don't see how your requests could not be promise-based. fetchUser1 doesn't have to be a promise, it can be your old user. Where fetchUser2 is the request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.