UNPKG

@harishreddym/baqend

Version:

Baqend JavaScript SDK

122 lines (106 loc) 3.55 kB
'use strict'; const deprecated = require('./deprecated'); const isLocked = Symbol('IsLocked'); const readyPromise = Symbol('ReadyPromise'); /** * This base class provides an lock interface to execute exclusive operations * @alias util.Lockable */ class Lockable { constructor() { /** * Indicates if there is currently an onging exclusive operation * @type boolean * @private */ this[isLocked] = false; /** * A promise which represents the state of the least exclusive operation * @type Promise * @private */ this[readyPromise] = Promise.resolve(this); } /** * Indicates if there is currently no exclusive operation executed * <code>true</code> If no exclusive lock is hold * @type {boolean} */ get isReady() { return !this[isLocked]; } /** * Waits on the previously requested operation and calls the doneCallback if the operation is fulfilled * @param {util.Lockable~doneCallback=} doneCallback The callback which will be invoked when the previously * operations on this object is completed. * @param {util.Lockable~failCallback=} failCallback When the lock can't be released caused by a none * recoverable error * @return {Promise<this>} A promise which completes successfully, when the previously requested * operation completes */ ready(doneCallback, failCallback) { return this[readyPromise].then(doneCallback, failCallback); } /** * Try to aquire an exclusive lock and executes the given callback. * @param {util.Lockable~callback} callback The exclusive operation to execute * @param {boolean} [critical=false] Indicates if the operation is critical. If the operation is critical and the * operation fails, then the lock will not be released * @return {Promise<T>} A promise * @throws {Error} If the lock can't be aquired * @alias util.Lockable.prototype.withLock<T> * @protected */ withLock(callback, critical) { if (this[isLocked]) { throw new Error('Current operation has not been finished.'); } try { this[isLocked] = true; const result = callback().then((res) => { this[isLocked] = false; return res; }, (e) => { if (!critical) { this[isLocked] = false; } throw e; }); this[readyPromise] = result.then(() => this, (e) => { if (!critical) { return this; } throw e; }); return result; } catch (e) { if (critical) { this[readyPromise] = Promise.reject(e); } else { this[isLocked] = false; } throw e; } } } deprecated(Lockable.prototype, '_isLocked', isLocked); deprecated(Lockable.prototype, '_readyPromise', readyPromise); module.exports = Lockable; /** * The operation callback is used by the {@link util.Lockable#withLock} method, * to perform an exclusive operation on the * @callback util.Lockable~callback * @return {Promise<T>} A Promise, which reflects the result of the operation */ /** * The done callback is called, when the last operation on this object completes * @callback util.Lockable~doneCallback * @param {this} entity This entity instance * @return {Promise<*>|*} A Promise, result or undefined */ /** * The fail callback is called, when the last critical operation on this object fails * @callback util.Lockable~failCallback * @param {Error} error The error which reject the operation * @return {Promise<*>|*} A Promise, result or undefined */