UNPKG

prisma-zod-generator

Version:

Prisma 2+ generator to emit Zod schemas from your Prisma schema

573 lines 14.4 kB
"use strict"; /** * Concurrency Control Utilities * * Provides mutex, semaphore, and atomic operation utilities * to prevent race conditions in PZG Pro */ Object.defineProperty(exports, "__esModule", { value: true }); exports.RateLimiter = exports.CircuitBreaker = exports.ConcurrentArray = exports.ConcurrentMap = exports.AtomicCounter = exports.ReadWriteLock = exports.Semaphore = exports.Mutex = void 0; exports.debounce = debounce; /** * Simple mutex implementation for async operations */ class Mutex { constructor() { this.locked = false; this.waitQueue = []; } async acquire() { return new Promise((resolve) => { if (!this.locked) { this.locked = true; resolve(this.createLock()); } else { this.waitQueue.push(resolve); } }); } createLock() { return { release: () => { if (this.waitQueue.length > 0) { const next = this.waitQueue.shift(); next(this.createLock()); } else { this.locked = false; } }, }; } isLocked() { return this.locked; } } exports.Mutex = Mutex; /** * Semaphore for limiting concurrent operations */ class Semaphore { constructor(permits) { this.waitQueue = []; this.permits = permits; } async acquire() { return new Promise((resolve) => { if (this.permits > 0) { this.permits--; resolve(() => this.release()); } else { this.waitQueue.push(() => { this.permits--; resolve(() => this.release()); }); } }); } release() { this.permits++; if (this.waitQueue.length > 0) { const next = this.waitQueue.shift(); next(); } } available() { return this.permits; } } exports.Semaphore = Semaphore; /** * Read-Write lock for concurrent read access */ class ReadWriteLock { constructor() { this.readers = 0; this.writers = 0; this.readWaitQueue = []; this.writeWaitQueue = []; } async acquireRead() { return new Promise((resolve) => { if (this.writers === 0 && this.writeWaitQueue.length === 0) { this.readers++; resolve(() => this.releaseRead()); } else { this.readWaitQueue.push(() => { this.readers++; resolve(() => this.releaseRead()); }); } }); } async acquireWrite() { return new Promise((resolve) => { if (this.readers === 0 && this.writers === 0) { this.writers++; resolve(() => this.releaseWrite()); } else { this.writeWaitQueue.push(() => { this.writers++; resolve(() => this.releaseWrite()); }); } }); } releaseRead() { this.readers--; if (this.readers === 0 && this.writeWaitQueue.length > 0) { const next = this.writeWaitQueue.shift(); next(); } } releaseWrite() { this.writers--; // Prioritize writers if any are waiting if (this.writeWaitQueue.length > 0) { const next = this.writeWaitQueue.shift(); next(); } else { // Release all waiting readers while (this.readWaitQueue.length > 0) { const next = this.readWaitQueue.shift(); next(); } } } } exports.ReadWriteLock = ReadWriteLock; /** * Atomic counter for safe increment/decrement operations */ class AtomicCounter { constructor() { this.value = 0; this.mutex = new Mutex(); } async increment() { const lock = await this.mutex.acquire(); try { return ++this.value; } finally { lock.release(); } } async decrement() { const lock = await this.mutex.acquire(); try { return --this.value; } finally { lock.release(); } } async get() { const lock = await this.mutex.acquire(); try { return this.value; } finally { lock.release(); } } async set(newValue) { const lock = await this.mutex.acquire(); try { this.value = newValue; } finally { lock.release(); } } async compareAndSwap(expected, newValue) { const lock = await this.mutex.acquire(); try { if (this.value === expected) { this.value = newValue; return true; } return false; } finally { lock.release(); } } } exports.AtomicCounter = AtomicCounter; /** * Thread-safe Map implementation */ class ConcurrentMap { constructor() { this.map = new Map(); this.rwLock = new ReadWriteLock(); } async get(key) { const release = await this.rwLock.acquireRead(); try { return this.map.get(key); } finally { release(); } } async set(key, value) { const release = await this.rwLock.acquireWrite(); try { this.map.set(key, value); } finally { release(); } } async delete(key) { const release = await this.rwLock.acquireWrite(); try { return this.map.delete(key); } finally { release(); } } async has(key) { const release = await this.rwLock.acquireRead(); try { return this.map.has(key); } finally { release(); } } async size() { const release = await this.rwLock.acquireRead(); try { return this.map.size; } finally { release(); } } async keys() { const release = await this.rwLock.acquireRead(); try { return Array.from(this.map.keys()); } finally { release(); } } async values() { const release = await this.rwLock.acquireRead(); try { return Array.from(this.map.values()); } finally { release(); } } async entries() { const release = await this.rwLock.acquireRead(); try { return Array.from(this.map.entries()); } finally { release(); } } async clear() { const release = await this.rwLock.acquireWrite(); try { this.map.clear(); } finally { release(); } } async forEach(callback) { const release = await this.rwLock.acquireRead(); try { this.map.forEach(callback); } finally { release(); } } /** * Atomic update operation - ensures consistency */ async update(key, updater) { const release = await this.rwLock.acquireWrite(); try { const current = this.map.get(key); const updated = updater(current); this.map.set(key, updated); return updated; } finally { release(); } } /** * Atomic upsert operation */ async upsert(key, initial, updater) { const release = await this.rwLock.acquireWrite(); try { const current = this.map.get(key); const value = current ? updater(current) : initial; this.map.set(key, value); return value; } finally { release(); } } } exports.ConcurrentMap = ConcurrentMap; /** * Thread-safe Array implementation */ class ConcurrentArray { constructor() { this.array = []; this.mutex = new Mutex(); } async push(...items) { const lock = await this.mutex.acquire(); try { return this.array.push(...items); } finally { lock.release(); } } async pop() { const lock = await this.mutex.acquire(); try { return this.array.pop(); } finally { lock.release(); } } async shift() { const lock = await this.mutex.acquire(); try { return this.array.shift(); } finally { lock.release(); } } async unshift(...items) { const lock = await this.mutex.acquire(); try { return this.array.unshift(...items); } finally { lock.release(); } } async length() { const lock = await this.mutex.acquire(); try { return this.array.length; } finally { lock.release(); } } async get(index) { const lock = await this.mutex.acquire(); try { return this.array[index]; } finally { lock.release(); } } async set(index, value) { const lock = await this.mutex.acquire(); try { this.array[index] = value; } finally { lock.release(); } } async slice(start, end) { const lock = await this.mutex.acquire(); try { return this.array.slice(start, end); } finally { lock.release(); } } async filter(predicate) { const lock = await this.mutex.acquire(); try { return this.array.filter(predicate); } finally { lock.release(); } } async forEach(callback) { const lock = await this.mutex.acquire(); try { this.array.forEach(callback); } finally { lock.release(); } } async clear() { const lock = await this.mutex.acquire(); try { this.array.length = 0; } finally { lock.release(); } } /** * Atomic batch operation */ async batch(operation) { const lock = await this.mutex.acquire(); try { return operation(this.array); } finally { lock.release(); } } } exports.ConcurrentArray = ConcurrentArray; /** * Debounce utility for preventing rapid successive calls */ function debounce(fn, delay) { let timeoutId = null; let resolvePromise = null; let rejectPromise = null; return (...args) => { return new Promise((resolve, reject) => { if (timeoutId) { clearTimeout(timeoutId); } resolvePromise = resolve; rejectPromise = reject; timeoutId = setTimeout(async () => { try { const result = await fn(...args); resolvePromise === null || resolvePromise === void 0 ? void 0 : resolvePromise(result); } catch (error) { rejectPromise === null || rejectPromise === void 0 ? void 0 : rejectPromise(error); } }, delay); }); }; } /** * Circuit breaker pattern for fault tolerance */ class CircuitBreaker { constructor(threshold = 5, timeout = 60000, monitoringPeriod = 10000) { this.threshold = threshold; this.timeout = timeout; this.monitoringPeriod = monitoringPeriod; this.state = 'closed'; this.failureCount = 0; this.nextAttempt = 0; this.successCount = 0; } async execute(operation) { if (this.state === 'open') { if (Date.now() < this.nextAttempt) { throw new Error('Circuit breaker is open'); } this.state = 'half-open'; this.successCount = 0; } try { const result = await operation(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } onSuccess() { this.failureCount = 0; if (this.state === 'half-open') { this.successCount++; if (this.successCount >= 3) { this.state = 'closed'; } } } onFailure() { this.failureCount++; if (this.failureCount >= this.threshold) { this.state = 'open'; this.nextAttempt = Date.now() + this.timeout; } } getState() { return this.state; } reset() { this.state = 'closed'; this.failureCount = 0; this.successCount = 0; this.nextAttempt = 0; } } exports.CircuitBreaker = CircuitBreaker; /** * Rate limiter for controlling request frequency */ class RateLimiter { constructor(capacity, refillRate, // tokens per second refillPeriod = 1000) { this.capacity = capacity; this.refillRate = refillRate; this.refillPeriod = refillPeriod; this.lastRefill = Date.now(); this.tokens = capacity; } async acquire(tokensRequested = 1) { this.refill(); if (this.tokens >= tokensRequested) { this.tokens -= tokensRequested; return true; } return false; } refill() { const now = Date.now(); const timePassed = now - this.lastRefill; const tokensToAdd = Math.floor((timePassed / this.refillPeriod) * this.refillRate); if (tokensToAdd > 0) { this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd); this.lastRefill = now; } } available() { this.refill(); return this.tokens; } } exports.RateLimiter = RateLimiter; //# sourceMappingURL=concurrency.js.map