@randajan/treelock
Version:
A minimal async lock with timeout support and parent-child queueing.
150 lines (145 loc) • 4.44 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.js
var index_exports = {};
__export(index_exports, {
TreeLock: () => TreeLock,
default: () => index_default
});
module.exports = __toCommonJS(index_exports);
// src/static.js
var import_sleep = require("@randajan/sleep");
var _privates = /* @__PURE__ */ new WeakMap();
var bfn = () => {
};
var Timeout = class extends Error {
};
var toInt = (num, min, max, errorName) => {
if (num == null) {
return;
}
const tp = typeof num;
if (tp !== "number") {
throw new Error(`Expects '${errorName}' to be a 'number' but received '${tp}'`);
}
if (min != null && num < min) {
throw new Error(`Expects '${errorName}' to be greater than '${min}' but received '${num}'`);
}
if (max != null && num > max) {
throw new Error(`Expects '${errorName}' to be lesser than '${max}' but received '${num}'`);
}
return Math.round(num);
};
var toTimeoutMs = (num) => toInt(num, 0, 2147483647, "timeout");
var withTimeout = (prom, tms) => {
if (!tms) {
return prom;
}
return Promise.race([prom, (0, import_sleep.timeout)(tms, new Timeout(`Execution time exceeded ${tms / 1e3}s`))]);
};
var toFn = (any, errorName) => {
if (any == null) {
return;
}
const tp = typeof any;
if (tp !== "function") {
throw new Error(`Expects '${errorName}' to be a 'number' but received '${tp}'`);
}
return any;
};
// src/TreeLock.js
var TreeLock = class _TreeLock {
constructor(options = {}) {
const { name, ttl, on, sup } = options;
const _pp = _privates.get(sup);
const _p = {
sup,
queue: Promise.resolve(),
ram: 0,
enqueue: !_pp ? (_) => _p.queue : (_) => Promise.all([_p.queue, _pp.queue]),
ttl: toTimeoutMs(ttl) ?? _pp?.ttl,
on: toFn(on) || _pp?.on || bfn
};
_p.append = (sub) => {
if (_p.subs) {
_p.subs.push(sub);
} else {
_p.subs = [sub];
const enq = _p.enqueue;
_p.enqueue = (_) => Promise.all([enq(), ..._p.subs.map((b) => b.queue)]);
}
};
const finish = () => _p.ram = Math.max(0, _p.ram - 1);
const done = (r) => {
finish();
_p.on(this, "done");
return r;
};
const crash = (err) => {
finish();
const status = err instanceof Timeout ? "timeout" : "error";
_p.on(this, status, err);
};
_p.run = (fn, tms, args) => {
_p.ram++;
if (this.ram + this.ramSup > 1) {
_p.on(this, "enter");
}
const exec = () => {
_p.on(this, "start");
return withTimeout(fn(...args), tms).then(done);
};
const next = _p.enqueue().then(exec);
_p.queue = next.catch(crash);
return next;
};
const enumerable = true;
Object.defineProperties(this, {
name: { value: name },
sup: { value: sup },
subs: { get: (_) => [..._p.subs] },
ram: { enumerable, get: (_) => _p.ram },
ramSup: { enumerable, get: !_pp ? (_) => 0 : (_) => sup.ram + sup.ramSup },
ramSub: { enumerable, get: (_) => _p.subs.reduce((r, s) => r + s.ram + s.ramSub, 0) },
queue: { get: (_) => _p.queue }
});
_privates.set(this, _p);
if (_pp) {
_pp.append(this);
}
}
run(fn, ttl, ...args) {
const _p = _privates.get(this);
ttl = toTimeoutMs(ttl) ?? _p.ttl;
return _p.run(fn, ttl, args);
}
wrap(fn, ttl) {
const _p = _privates.get(this);
ttl = toTimeoutMs(ttl) ?? _p.ttl;
return (...args) => _p.run(fn, ttl, args);
}
sub(options = {}) {
return new _TreeLock({
...options,
sup: this
});
}
};
// src/index.js
var index_default = (options = {}) => new TreeLock(options);
//# sourceMappingURL=index.js.map