rwlockfile
Version:
lockfile utility with reader/writers
97 lines (96 loc) • 3.22 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
function lockfile(prop, opts = {}) {
const Lockfile = require('./lockfile').default;
return methodDecorator(function ({ original, propertyName }) {
return function (...args) {
const lockfile = this[prop];
if (!(lockfile instanceof Lockfile)) {
throw new Error('prop does not point to a Lockfile instance');
}
if (opts.sync) {
lockfile.addSync({ reason: propertyName.toString() });
try {
return original.apply(this, args);
}
finally {
lockfile.removeSync();
}
}
else {
return (async () => {
await lockfile.add({ reason: propertyName.toString() });
try {
return await original.apply(this, args);
}
finally {
await lockfile.remove();
}
})();
}
};
});
}
exports.lockfile = lockfile;
function rwlockfile(prop, type, opts = {}) {
const RWLockfile = require('./rwlockfile').default;
return methodDecorator(function ({ original, propertyName }) {
return async function (...args) {
const lockfile = this[prop];
if (!(lockfile instanceof RWLockfile)) {
throw new Error('prop does not point to a Lockfile instance');
}
const addOpts = {
reason: propertyName.toString(),
};
if (opts.ifLocked) {
addOpts.ifLocked = () => this[opts.ifLocked]();
}
await lockfile.add(type, addOpts);
let result;
try {
result = await original.apply(this, args);
}
finally {
await lockfile.remove(type);
}
return result;
};
});
}
exports.rwlockfile = rwlockfile;
function onceAtATime(argKey) {
return methodDecorator(function ({ original }) {
const key = Symbol('onceAtATime');
return async function (...args) {
const subKey = argKey !== undefined ? args[argKey] : key;
const cache = (this[key] = this[key] || {});
if (cache[subKey])
return cache[subKey];
cache[subKey] = original.apply(this, args);
try {
return await cache[subKey];
}
finally {
delete cache[subKey];
}
};
});
}
exports.onceAtATime = onceAtATime;
function methodDecorator(fn) {
return (target, propertyName, descriptor) => {
if (isMethodDecorator(descriptor)) {
descriptor.value = fn({ target, propertyName, descriptor, original: descriptor.value });
return descriptor;
}
else {
throw new Error(`${propertyName} on ${target} is not a a method`);
}
};
}
function isMethodDecorator(prop) {
if (!prop)
return false;
return !!prop.value;
}
;