@sirmrmarty/n8n-nodes-tmux-orchestrator
Version:
n8n nodes for orchestrating Claude AI agents through tmux sessions
383 lines • 10.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stateManager = exports.StateManager = exports.ThreadSafeQueue = exports.ThreadSafeCounter = exports.ThreadSafeSet = exports.ThreadSafeMap = void 0;
const events_1 = require("events");
class ThreadSafeMap extends events_1.EventEmitter {
constructor(lockTimeout = 5000) {
super();
this.map = new Map();
this.locks = new Set();
this.lockTimeout = lockTimeout;
}
async acquireLock(key) {
const lockId = `${String(key)}_${Date.now()}_${Math.random()}`;
const keyStr = String(key);
while (this.locks.has(keyStr)) {
await new Promise(resolve => setTimeout(resolve, 10));
}
this.locks.add(keyStr);
setTimeout(() => {
if (this.locks.has(keyStr)) {
console.warn(`Lock timeout for key ${keyStr}, forcibly releasing`);
this.locks.delete(keyStr);
}
}, this.lockTimeout);
return lockId;
}
releaseLock(key) {
this.locks.delete(String(key));
}
async safeSet(key, value) {
await this.acquireLock(key);
try {
const oldValue = this.map.get(key);
this.map.set(key, value);
this.emit('change', { key, oldValue, newValue: value, operation: 'set' });
}
finally {
this.releaseLock(key);
}
}
safeGet(key) {
return this.map.get(key);
}
async safeDelete(key) {
await this.acquireLock(key);
try {
const oldValue = this.map.get(key);
const deleted = this.map.delete(key);
if (deleted) {
this.emit('change', { key, oldValue, newValue: undefined, operation: 'delete' });
}
return deleted;
}
finally {
this.releaseLock(key);
}
}
safeHas(key) {
return this.map.has(key);
}
safeKeys() {
return Array.from(this.map.keys());
}
safeValues() {
return Array.from(this.map.values());
}
safeEntries() {
return Array.from(this.map.entries());
}
safeSize() {
return this.map.size;
}
async safeClear() {
const keys = this.safeKeys();
for (const key of keys) {
await this.acquireLock(key);
}
try {
this.map.clear();
this.emit('change', { operation: 'clear' });
}
finally {
for (const key of keys) {
this.releaseLock(key);
}
}
}
async safeUpdate(key, updateFn) {
await this.acquireLock(key);
try {
const oldValue = this.map.get(key);
const newValue = updateFn(oldValue);
this.map.set(key, newValue);
this.emit('change', { key, oldValue, newValue, operation: 'update' });
return newValue;
}
finally {
this.releaseLock(key);
}
}
async safeComputeIfAbsent(key, computeFn) {
await this.acquireLock(key);
try {
if (this.map.has(key)) {
return this.map.get(key);
}
const value = await Promise.resolve(computeFn());
this.map.set(key, value);
this.emit('change', { key, oldValue: undefined, newValue: value, operation: 'compute' });
return value;
}
finally {
this.releaseLock(key);
}
}
}
exports.ThreadSafeMap = ThreadSafeMap;
class ThreadSafeSet extends events_1.EventEmitter {
constructor(lockTimeout = 5000) {
super();
this.set = new Set();
this.locks = new Set();
this.lockTimeout = lockTimeout;
}
async acquireLock() {
const lockId = `set_${Date.now()}_${Math.random()}`;
while (this.locks.size > 0) {
await new Promise(resolve => setTimeout(resolve, 10));
}
this.locks.add(lockId);
setTimeout(() => {
if (this.locks.has(lockId)) {
console.warn(`Set lock timeout, forcibly releasing`);
this.locks.delete(lockId);
}
}, this.lockTimeout);
}
releaseLock() {
this.locks.clear();
}
async safeAdd(value) {
await this.acquireLock();
try {
const hadValue = this.set.has(value);
this.set.add(value);
if (!hadValue) {
this.emit('change', { value, operation: 'add' });
}
return !hadValue;
}
finally {
this.releaseLock();
}
}
async safeDelete(value) {
await this.acquireLock();
try {
const deleted = this.set.delete(value);
if (deleted) {
this.emit('change', { value, operation: 'delete' });
}
return deleted;
}
finally {
this.releaseLock();
}
}
safeHas(value) {
return this.set.has(value);
}
safeValues() {
return Array.from(this.set.values());
}
safeSize() {
return this.set.size;
}
async safeClear() {
await this.acquireLock();
try {
this.set.clear();
this.emit('change', { operation: 'clear' });
}
finally {
this.releaseLock();
}
}
}
exports.ThreadSafeSet = ThreadSafeSet;
class ThreadSafeCounter extends events_1.EventEmitter {
constructor() {
super(...arguments);
this.value = 0;
this.lock = false;
}
async increment(amount = 1) {
while (this.lock) {
await new Promise(resolve => setTimeout(resolve, 1));
}
this.lock = true;
try {
const oldValue = this.value;
this.value += amount;
this.emit('change', { oldValue, newValue: this.value, operation: 'increment' });
return this.value;
}
finally {
this.lock = false;
}
}
async decrement(amount = 1) {
return this.increment(-amount);
}
getValue() {
return this.value;
}
async setValue(newValue) {
while (this.lock) {
await new Promise(resolve => setTimeout(resolve, 1));
}
this.lock = true;
try {
const oldValue = this.value;
this.value = newValue;
this.emit('change', { oldValue, newValue, operation: 'set' });
return this.value;
}
finally {
this.lock = false;
}
}
async compareAndSwap(expected, newValue) {
while (this.lock) {
await new Promise(resolve => setTimeout(resolve, 1));
}
this.lock = true;
try {
if (this.value === expected) {
const oldValue = this.value;
this.value = newValue;
this.emit('change', { oldValue, newValue, operation: 'compareAndSwap' });
return true;
}
return false;
}
finally {
this.lock = false;
}
}
}
exports.ThreadSafeCounter = ThreadSafeCounter;
class ThreadSafeQueue extends events_1.EventEmitter {
constructor() {
super(...arguments);
this.queue = [];
this.lock = false;
}
async acquireLock() {
while (this.lock) {
await new Promise(resolve => setTimeout(resolve, 1));
}
this.lock = true;
}
releaseLock() {
this.lock = false;
}
async enqueue(item) {
await this.acquireLock();
try {
this.queue.push(item);
this.emit('enqueue', item);
}
finally {
this.releaseLock();
}
}
async dequeue() {
await this.acquireLock();
try {
const item = this.queue.shift();
if (item !== undefined) {
this.emit('dequeue', item);
}
return item;
}
finally {
this.releaseLock();
}
}
peek() {
return this.queue[0];
}
size() {
return this.queue.length;
}
isEmpty() {
return this.queue.length === 0;
}
async clear() {
await this.acquireLock();
try {
this.queue = [];
this.emit('clear');
}
finally {
this.releaseLock();
}
}
}
exports.ThreadSafeQueue = ThreadSafeQueue;
class StateManager {
constructor() {
this.maps = new Map();
this.sets = new Map();
this.counters = new Map();
this.queues = new Map();
}
static getInstance() {
if (!StateManager.instance) {
StateManager.instance = new StateManager();
}
return StateManager.instance;
}
getMap(name) {
if (!this.maps.has(name)) {
this.maps.set(name, new ThreadSafeMap());
}
return this.maps.get(name);
}
getSet(name) {
if (!this.sets.has(name)) {
this.sets.set(name, new ThreadSafeSet());
}
return this.sets.get(name);
}
getCounter(name) {
if (!this.counters.has(name)) {
this.counters.set(name, new ThreadSafeCounter());
}
return this.counters.get(name);
}
getQueue(name) {
if (!this.queues.has(name)) {
this.queues.set(name, new ThreadSafeQueue());
}
return this.queues.get(name);
}
removeState(name) {
const removed = this.maps.delete(name) ||
this.sets.delete(name) ||
this.counters.delete(name) ||
this.queues.delete(name);
return removed;
}
getStats() {
return {
maps: this.maps.size,
sets: this.sets.size,
counters: this.counters.size,
queues: this.queues.size,
total: this.maps.size + this.sets.size + this.counters.size + this.queues.size
};
}
async clearAll() {
const promises = [];
for (const map of this.maps.values()) {
promises.push(map.safeClear());
}
for (const set of this.sets.values()) {
promises.push(set.safeClear());
}
for (const queue of this.queues.values()) {
promises.push(queue.clear());
}
await Promise.all(promises);
this.maps.clear();
this.sets.clear();
this.counters.clear();
this.queues.clear();
}
}
exports.StateManager = StateManager;
exports.stateManager = StateManager.getInstance();
//# sourceMappingURL=threadSafeState.js.map