Posts / promiseLock#17

Promise Lock

By Toby Hinloopen at 2021-04-02 16:28

Installation

# npm
npm i https://boomm.io/p/17-promise-lock.tar.gz
# yarn
yarn add https://boomm.io/p/17-promise-lock.tar.gz

Usage

const promiseLock = require("17-promise-lock");

Source

// FROM: https://gist.github.com/MikeyBurkman/fe6af4793b68d75ca9466a1c14ea30c1

'use strict';

module.exports = {
  createSingleLock: createSingleLock,
  createKeyedLock: createKeyedLock
};

// Maintains a list of locks referenced by keys
function createKeyedLock() {
  const locks = {};

  return function execute(id, fn) {
    let entry;
    if (locks[id]) {
      entry = locks[id];
    } else {
      entry = locks[id] = {
        pending: 0,
        lock: createSingleLock()
      };
    }

    entry.pending += 1;
    const decrementPending = () => {
      entry.pending -= 1;
      if (entry.pending === 0) {
        locks[id] = undefined;
      }
    };

    return entry.lock(fn)
      .then((r) => {
        decrementPending();
        return r;
      }, (err) => {
        decrementPending();
        throw err;
      })
  };
}

function createSingleLock() {
  const queue = [];
  let locked = false;

  return function execute(fn) {
    return acquire()
      .then(fn)
      .then((r) => {
        release();
        return r;
      }, (err) => {
        release();
        throw err;
      })
  };

  function acquire() {
    if (locked) {
      return new Promise((resolve) => queue.push(resolve));
    } else {
      locked = true;
      return Promise.resolve();
    }
  }

  function release() {
    const next = queue.shift();
    if (next) {
      next();
    } else {
      locked = false;
    }
  }
}