Home > OS >  Express JS: how does it handle simultaneous requests and avoid collision?
Express JS: how does it handle simultaneous requests and avoid collision?

Time:11-23

I am new to nodejs/Express.js development.

I have built my backend service with Express.js / Typescript and I have multiple routes / api endpoints defined. One is like this:

app.post('/api/issues/new', createNewIssue); 

where browser will send a post request when a user submits a new photo (also called an issue in my app).

The user can send an issue to another user, and the backend will first query the database to find the number of issues that matches the conditions of "source user" and "destination user", and then give the new issue an identifying ID in the form srcUser-dstUser-[number], where number is the auto-incremented count.

The createNewIssue function is like this:

export const createNewIssue = catchErrors(async (req, res) => {
  
  const srcUser = req.header('src_username');
  const dstUser = req.header('dst_username');
  
  // query database for number of issues matching "srcUser" and "dstUser"
  ...
  const lastIssues = await Issue.find( {where: {"srcUser": srcUser, "dstUser": dstUser}, order: { id: 'DESC'}}); 
  const count = lastIssues.length;

  // create a new issue Entity with the ID `srcUser-dstUser-[count 1]`
  const newIssue = await createEntity(Issue, {
   ...
  id: `srcUser-dstUser-${count 1}`,
   ... 
  });


  res.respond({ newIssue: newIssue}); 
})

Say the backend receives multiple requests with the same srcUser and dstUser attributes at the same time, will there be collisions where multiple new issues are created with the same id?

I have read some documentation about nodejs being single-threaded, but I'm not sure what that means definitely for this specific scenario.


Besides business logic in this scenario, I have some confusions in general about Express JS / Node JS:

When there is only one cpu core, Express JS process multiple concurrent requests asynchronously: it starts processing one and does not wait for it to finish, instead continues to process the next one. Is this understanding accurate?

When there are multiple cpu cores, does Express JS / Node Js utilize them all in the same manner?

CodePudding user response:

Node.js will not solve this problem for you automatically.

While it will only deal with one thing at a time, it is entirely possible that Request 2 will request the latest ID in the database while Request 1 has hit the await statement at the same point and gone to sleep. This would mean they get the same answer and would each try to create a new entry with the same ID.

You need to write your JavaScript to make sure that this doesn't happen.

The usual ways to handle this would be to either:

  • Let the database (and not your JavaScript) handle the ID generation (usually by using a sequence.
  • Use transactions so that the request for the latest ID and the insertion of the new row are treated as one operation by the database (so it won't start the same operation for Request 2 until the select and insert for Request 1 are both done).
  • Test to make sure createEntity is successful (and doesn't throw a 'duplicate id' error) and try again if it fails (with a limit in case it keeps failing in which case it should return an error message to the client).

The specifics depend on which database you use. I linked to the Postgresql documentation for the sake of example.

  • Related