title: Implementing Lock in Node.js
body: <p><strong>Preface:</strong></p>
  
  <p>In order to solve my problem, you have to have knowledge in the following areas: thread-safety, Promise, async-await.</p>
  
  <p>For people who are not familiar with TypeScript, it's just normal JavaScript (ES6) with type annotations.</p>
  
  <hr>
  
  <p>I have a function named <code>excludeItems</code> that accepts an item list (each item is a string), and calls an API (that excludes the item) for each item. It's important not to call the API twice for the same item, not even in different executions of the function, so I save in a local DB the items that are already excluded.</p>
  
  <pre><code>async function excludeItems(items: string[]) {
              var excludedItems = await db.getExcludedItems();
  
              for (var i in items) {
                  var item = items[i];
                  var isAlreadyExcluded = excludedItems.find(excludedItem =&gt; excludedItem == item);
  
                  if (isAlreadyExcluded) {
                      continue;
                  }
  
                  await someApi.excludeItem(item);
                  await db.addExcludedItem(item);
              }
       }
  </code></pre>
  
  <p>This function is called asynchronously by its client several times instantaneously, meaning the client calls the function say 5 times before the first execution is completed.</p>
  
  <p>A concrete scenario:</p>
  
  <pre><code>excludeItems([]);
  excludeItems(['A','B','C']);
  excludeItems([]);
  excludeItems(['A','C']);
  excludeItems([]);
  </code></pre>
  
  <p>In this case, although Node.js is single-threaded, the Critical Section problem is existing here, and I get the wrong results. This is my "excludedItems" collection in my local DB after the execution of that scenario:</p>
  
  <pre><code>[{item: 'A'},
  {item: 'B'},
  {item: 'C'},
  {item: 'A'},
  {item: 'C'}]
  </code></pre>
  
  <p>As you can see, the last 'A' and 'C' are redundant (meaning that the API was also called twice for these items).</p>
  
  <p>It occurs due to the <code>await</code> statements in the code. Every time an await statement is reached, a new Promise is created under the hood, therefore although Node.js is single-threaded, the next async function that was waiting to be executed is getting executed, and that way this critical section is executed parallelly. </p>
  
  <p>To solve that problem, I've implemented a locking mechanism:</p>
  
  <pre><code>var excludedItemsLocker = false;
  async function safeExcludeItems(items: string[]) {
          while (excludedItemsLocker) {
              await sleep(100);
          }
      try {
          excludedItemsLocker = true;
  
          var excludedItems: string[] = await db.getExcludedItems();
  
          for (var i in items) {
              var item = items[i];
              var isAlreadyExcluded = excludedItems.find(excludedItem =&gt; excludedItem == item);
  
              if (isAlreadyExcluded) {
                  continue;
              }
  
              await someApi.excludeItem(item);
              await db.addExcludedItem(item);
          }
      }
      finally {
          excludedItemsLocker = false;
      }
  }
  
  async function sleep(duration: number): Promise&lt;Object&gt; {
      return new Promise(function (resolve) {
          setTimeout(resolve, duration);
      });
  }
  </code></pre>
  
  <p>However, this implementation does not work for some reason. I still get more than one (alleged) "thread" in the critical section, meaning it's still getting executed parallelly and my local DB is filled with the same wrong results. BTW the <code>sleep</code> method works as expected, its purpose is just to give CPU time to the next function call that's waiting to be executed.</p>
  
  <p>Does anybody see what's broken in my implementation?</p>
  
  <p>BTW I know that I can achieve the same goal without implementing a Lock, for example by calling to <code>db.getExcludedItems</code> inside the loop, but I want to know why my Lock implementation is broken.</p>