Search code examples
javascriptnode.jselasticsearchevent-loop

General node.js/javascript question and event loop


I have following problem: I let two functions write into my database. Before they get inserted into the database I check if a similar item exists:

const storeListing = async listing => {
   //Some logic
   const foundSimilar = await findSimilar(listing);
  if(!foundSimilar){
     await insertListing(listing)
  }else{
    //Perform duplicate check
    if(foundSimilar.buildingType===listing.buildingType){
       console.log('found')
    }
  }
}

Now when I do following:

const test = () => {
  storeListing({buildingType:'MFH'});
  storeListing({buildingType:'MFH'});
}

The else condition with the duplicate check is never triggered.

My idea would be that the two functions get handled sequentially (event loop). So storeListing can not be called again before one is done.

So do I have a logical issue here or is it just the database having eventual consistency?


Edit: When I do not know how many other functions call storeListing and I want it to happen serialized (e.g. I have storeListing for Multi family house - store listing for single family house).

Is this a good pattern:

const lock={};
export const storeListing = async (listing, type) => {
  const id= uuidv1();

  while (Object.keys(lock).length>0){
    await timeout(15);
  }
  threadLock[id]=true;
  //Function like above

  delete lock[id];
}

Solution

  • Even if the insertion order isn't relevant you still need to use await in order to avoid race conditions.

    Your full code queues up the following I/O operations:

    1. findSimilarOne
    2. insertListingOne (if findSimilarOne returns no match)
    3. findSimilarTwo
    4. insertListingTwo (if findSimilarTwo returns no match)

    The only restrictions on the ordering of these operations is that #1 must occur before #2, and #3 must occur before #4.

    The order that these are completing in is: #1, #3, #2, #4

    Because both findSimilar calls complete before either insertListing completes, they both return no match.

    You should use async, like so:

    let test = async () => {
      await storeListing({ buildingType:'MFH' });
      await storeListing({ buildingType:'MFH' });
    };
    

    This enforces a new restriction on the operation order: that #2 must occur before #3