UNPKG

@klastra/ksync

Version:

Real-time sync engine for modern applications with 300k+ ops/sec performance

89 lines 3.33 kB
export class MemoryStorage { events = []; options; memoryUsageBytes = 0; constructor(options = {}) { this.options = { maxEvents: options.maxEvents ?? 10000, maxMemoryMB: options.maxMemoryMB ?? 50, trimOnLimit: options.trimOnLimit ?? true, compressionEnabled: options.compressionEnabled ?? false }; } async getEvents(fromVersion) { if (fromVersion === undefined) { return [...this.events]; } return this.events.filter(event => event.version > fromVersion); } async storeEvent(event) { await this.storeEvents([event]); } async storeEvents(events) { // Calculate memory usage of new events const newEventSize = this.calculateEventSize(events); // Check memory limits before adding if (this.memoryUsageBytes + newEventSize > this.options.maxMemoryMB * 1024 * 1024) { if (this.options.trimOnLimit) { await this.trimToFitMemory(newEventSize); } else { throw new Error(`Memory limit exceeded: ${this.options.maxMemoryMB}MB`); } } this.events.push(...events); this.memoryUsageBytes += newEventSize; // Check event count limits if (this.events.length > this.options.maxEvents) { if (this.options.trimOnLimit) { const eventsToRemove = this.events.length - this.options.maxEvents; const removedEvents = this.events.splice(0, eventsToRemove); this.memoryUsageBytes -= this.calculateEventSize(removedEvents); } else { throw new Error(`Event limit exceeded: ${this.options.maxEvents} events`); } } } async saveEvents(events) { return this.storeEvents(events); } async loadEvents() { return [...this.events]; } async getLastVersion() { if (this.events.length === 0) return 0; return Math.max(...this.events.map(e => e.version)); } async clear() { this.events = []; this.memoryUsageBytes = 0; } // Get storage statistics getStats() { return { eventCount: this.events.length, memoryUsageBytes: this.memoryUsageBytes, memoryUsageMB: this.memoryUsageBytes / (1024 * 1024), memoryUtilization: (this.memoryUsageBytes / (this.options.maxMemoryMB * 1024 * 1024)) * 100, maxEvents: this.options.maxEvents, maxMemoryMB: this.options.maxMemoryMB }; } calculateEventSize(events) { // Rough estimation of memory usage return events.reduce((total, event) => { const eventString = JSON.stringify(event); return total + (eventString.length * 2); // UTF-16 uses 2 bytes per character }, 0); } async trimToFitMemory(requiredBytes) { const targetMemory = (this.options.maxMemoryMB * 1024 * 1024) - requiredBytes; while (this.memoryUsageBytes > targetMemory && this.events.length > 0) { const removedEvent = this.events.shift(); this.memoryUsageBytes -= this.calculateEventSize([removedEvent]); } } } //# sourceMappingURL=memory.js.map