"use strict"; /** * Mutex decorator for exclusive method execution * * Without arguments: Per-instance locking (each object has its own lock per method) * @mutex * async my_method() { ... } * * With ID argument: Global locking by ID (all instances share the lock) * @mutex('operation_name') * async my_method() { ... } * * @decorator * @param {string} [global_id] - Optional global mutex ID for cross-instance locking */ function mutex(global_id) { // Storage (using IIFEs to keep WeakMap/Map in closure scope) const instance_mutexes = function () { if (!mutex._instance_storage) { mutex._instance_storage = new WeakMap(); } return mutex._instance_storage; }(); const global_mutexes = function () { if (!mutex._global_storage) { mutex._global_storage = new Map(); } return mutex._global_storage; }(); /** * Get or create a mutex for a specific instance and method */ function get_instance_mutex(instance, method_name) { let instance_locks = instance_mutexes.get(instance); if (!instance_locks) { instance_locks = new Map(); instance_mutexes.set(instance, instance_locks); } let lock_state = instance_locks.get(method_name); if (!lock_state) { lock_state = { active: false, queue: [] }; instance_locks.set(method_name, lock_state); } return lock_state; } /** * Get or create a global mutex by ID */ function get_global_mutex(id) { let lock_state = global_mutexes.get(id); if (!lock_state) { lock_state = { active: false, queue: [] }; global_mutexes.set(id, lock_state); } return lock_state; } /** * Execute the next queued operation for a mutex */ function schedule_next(lock_state) { if (lock_state.active || lock_state.queue.length === 0) { return; } const { fn, resolve, reject } = lock_state.queue.shift(); lock_state.active = true; Promise.resolve().then(fn).then(resolve, reject).finally(() => { lock_state.active = false; schedule_next(lock_state); }); } /** * Acquire a mutex lock and execute callback */ function acquire_lock(lock_state, fn) { return new Promise((resolve, reject) => { lock_state.queue.push({ fn, resolve, reject }); schedule_next(lock_state); }); } // If called with an ID argument: @mutex('id') if (typeof global_id === 'string') { return function (target, key, descriptor) { const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } const lock_state = get_global_mutex(global_id); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; }; } // If called without arguments: @mutex (target is the first argument) const target = global_id; // In this case, first arg is target const key = arguments[1]; const descriptor = arguments[2]; const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } const lock_state = get_instance_mutex(this, key); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJtdXRleCIsImdsb2JhbF9pZCIsImluc3RhbmNlX211dGV4ZXMiLCJfaW5zdGFuY2Vfc3RvcmFnZSIsIldlYWtNYXAiLCJnbG9iYWxfbXV0ZXhlcyIsIl9nbG9iYWxfc3RvcmFnZSIsIk1hcCIsImdldF9pbnN0YW5jZV9tdXRleCIsImluc3RhbmNlIiwibWV0aG9kX25hbWUiLCJpbnN0YW5jZV9sb2NrcyIsImdldCIsInNldCIsImxvY2tfc3RhdGUiLCJhY3RpdmUiLCJxdWV1ZSIsImdldF9nbG9iYWxfbXV0ZXgiLCJpZCIsInNjaGVkdWxlX25leHQiLCJsZW5ndGgiLCJmbiIsInJlc29sdmUiLCJyZWplY3QiLCJzaGlmdCIsIlByb21pc2UiLCJ0aGVuIiwiZmluYWxseSIsImFjcXVpcmVfbG9jayIsInB1c2giLCJ0YXJnZXQiLCJrZXkiLCJkZXNjcmlwdG9yIiwib3JpZ2luYWxfbWV0aG9kIiwidmFsdWUiLCJFcnJvciIsIl9sZW4iLCJhcmd1bWVudHMiLCJhcmdzIiwiQXJyYXkiLCJfa2V5IiwiYXBwbHkiLCJfbGVuMiIsIl9rZXkyIl0sInNvdXJjZXMiOlsiYXBwL1JTcGFkZS9Db3JlL0pzL011dGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTXV0ZXggZGVjb3JhdG9yIGZvciBleGNsdXNpdmUgbWV0aG9kIGV4ZWN1dGlvblxuICpcbiAqIFdpdGhvdXQgYXJndW1lbnRzOiBQZXItaW5zdGFuY2UgbG9ja2luZyAoZWFjaCBvYmplY3QgaGFzIGl0cyBvd24gbG9jayBwZXIgbWV0aG9kKVxuICogICBAbXV0ZXhcbiAqICAgYXN5bmMgbXlfbWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIFdpdGggSUQgYXJndW1lbnQ6IEdsb2JhbCBsb2NraW5nIGJ5IElEIChhbGwgaW5zdGFuY2VzIHNoYXJlIHRoZSBsb2NrKVxuICogICBAbXV0ZXgoJ29wZXJhdGlvbl9uYW1lJylcbiAqICAgYXN5bmMgbXlfbWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIEBkZWNvcmF0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBbZ2xvYmFsX2lkXSAtIE9wdGlvbmFsIGdsb2JhbCBtdXRleCBJRCBmb3IgY3Jvc3MtaW5zdGFuY2UgbG9ja2luZ1xuICovXG5mdW5jdGlvbiBtdXRleChnbG9iYWxfaWQpIHtcbiAgICAvLyBTdG9yYWdlICh1c2luZyBJSUZFcyB0byBrZWVwIFdlYWtNYXAvTWFwIGluIGNsb3N1cmUgc2NvcGUpXG4gICAgY29uc3QgaW5zdGFuY2VfbXV0ZXhlcyA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCFtdXRleC5faW5zdGFuY2Vfc3RvcmFnZSkge1xuICAgICAgICAgICAgbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2UgPSBuZXcgV2Vha01hcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdXRleC5faW5zdGFuY2Vfc3RvcmFnZTtcbiAgICB9KSgpO1xuXG4gICAgY29uc3QgZ2xvYmFsX211dGV4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghbXV0ZXguX2dsb2JhbF9zdG9yYWdlKSB7XG4gICAgICAgICAgICBtdXRleC5fZ2xvYmFsX3N0b3JhZ2UgPSBuZXcgTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG11dGV4Ll9nbG9iYWxfc3RvcmFnZTtcbiAgICB9KSgpO1xuXG4gICAgLyoqXG4gICAgICogR2V0IG9yIGNyZWF0ZSBhIG11dGV4IGZvciBhIHNwZWNpZmljIGluc3RhbmNlIGFuZCBtZXRob2RcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRfaW5zdGFuY2VfbXV0ZXgoaW5zdGFuY2UsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIGxldCBpbnN0YW5jZV9sb2NrcyA9IGluc3RhbmNlX211dGV4ZXMuZ2V0KGluc3RhbmNlKTtcbiAgICAgICAgaWYgKCFpbnN0YW5jZV9sb2Nrcykge1xuICAgICAgICAgICAgaW5zdGFuY2VfbG9ja3MgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICBpbnN0YW5jZV9tdXRleGVzLnNldChpbnN0YW5jZSwgaW5zdGFuY2VfbG9ja3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxvY2tfc3RhdGUgPSBpbnN0YW5jZV9sb2Nrcy5nZXQobWV0aG9kX25hbWUpO1xuICAgICAgICBpZiAoIWxvY2tfc3RhdGUpIHtcbiAgICAgICAgICAgIGxvY2tfc3RhdGUgPSB7IGFjdGl2ZTogZmFsc2UsIHF1ZXVlOiBbXSB9O1xuICAgICAgICAgICAgaW5zdGFuY2VfbG9ja3Muc2V0KG1ldGhvZF9uYW1lLCBsb2NrX3N0YXRlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsb2NrX3N0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBvciBjcmVhdGUgYSBnbG9iYWwgbXV0ZXggYnkgSURcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRfZ2xvYmFsX211dGV4KGlkKSB7XG4gICAgICAgIGxldCBsb2NrX3N0YXRlID0gZ2xvYmFsX211dGV4ZXMuZ2V0KGlkKTtcbiAgICAgICAgaWYgKCFsb2NrX3N0YXRlKSB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlID0geyBhY3RpdmU6IGZhbHNlLCBxdWV1ZTogW10gfTtcbiAgICAgICAgICAgIGdsb2JhbF9tdXRleGVzLnNldChpZCwgbG9ja19zdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvY2tfc3RhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXhlY3V0ZSB0aGUgbmV4dCBxdWV1ZWQgb3BlcmF0aW9uIGZvciBhIG11dGV4XG4gICAgICovXG4gICAgZnVuY3Rpb24gc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKSB7XG4gICAgICAgIGlmIChsb2NrX3N0YXRlLmFjdGl2ZSB8fCBsb2NrX3N0YXRlLnF1ZXVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBmbiwgcmVzb2x2ZSwgcmVqZWN0IH0gPSBsb2NrX3N0YXRlLnF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgIGxvY2tfc3RhdGUuYWN0aXZlID0gdHJ1ZTtcblxuICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgLnRoZW4oZm4pXG4gICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpXG4gICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9ja19zdGF0ZS5hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBzY2hlZHVsZV9uZXh0KGxvY2tfc3RhdGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWNxdWlyZSBhIG11dGV4IGxvY2sgYW5kIGV4ZWN1dGUgY2FsbGJhY2tcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgZm4pIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGxvY2tfc3RhdGUucXVldWUucHVzaCh7IGZuLCByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICBzY2hlZHVsZV9uZXh0KGxvY2tfc3RhdGUpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBJZiBjYWxsZWQgd2l0aCBhbiBJRCBhcmd1bWVudDogQG11dGV4KCdpZCcpXG4gICAgaWYgKHR5cGVvZiBnbG9iYWxfaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbih0YXJnZXQsIGtleSwgZGVzY3JpcHRvcikge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxfbWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbF9tZXRob2QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEBtdXRleCBjYW4gb25seSBiZSBhcHBsaWVkIHRvIG1ldGhvZHMgKHRyaWVkIHRvIGFwcGx5IHRvICR7a2V5fSlgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uKC4uLmFyZ3MpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsb2NrX3N0YXRlID0gZ2V0X2dsb2JhbF9tdXRleChnbG9iYWxfaWQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgKCkgPT4gb3JpZ2luYWxfbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIElmIGNhbGxlZCB3aXRob3V0IGFyZ3VtZW50czogQG11dGV4ICh0YXJnZXQgaXMgdGhlIGZpcnN0IGFyZ3VtZW50KVxuICAgIGNvbnN0IHRhcmdldCA9IGdsb2JhbF9pZDsgIC8vIEluIHRoaXMgY2FzZSwgZmlyc3QgYXJnIGlzIHRhcmdldFxuICAgIGNvbnN0IGtleSA9IGFyZ3VtZW50c1sxXTtcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gYXJndW1lbnRzWzJdO1xuXG4gICAgY29uc3Qgb3JpZ2luYWxfbWV0aG9kID0gZGVzY3JpcHRvci52YWx1ZTtcblxuICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxfbWV0aG9kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQG11dGV4IGNhbiBvbmx5IGJlIGFwcGxpZWQgdG8gbWV0aG9kcyAodHJpZWQgdG8gYXBwbHkgdG8gJHtrZXl9KWApO1xuICAgIH1cblxuICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgIGNvbnN0IGxvY2tfc3RhdGUgPSBnZXRfaW5zdGFuY2VfbXV0ZXgodGhpcywga2V5KTtcbiAgICAgICAgcmV0dXJuIGFjcXVpcmVfbG9jayhsb2NrX3N0YXRlLCAoKSA9PiBvcmlnaW5hbF9tZXRob2QuYXBw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