buflux
Version:
A high-performance, event-driven buffer library for Node.js and browsers, with configurable overflow strategies
123 lines (122 loc) • 3.75 kB
JavaScript
import { EventEmitter } from './event-emitter';
import { OverflowMode } from '../types/overflow-mode.enum';
/**
* A fixed-capacity buffer with configurable overflow strategies
* @template T The type of items stored in the buffer
* @extends EventEmitter<T>
*/
export class Buflux extends EventEmitter {
/**
* Creates a new Buflux instance
* @param {BufluxOptions} options - Configuration options
* @throws {Error} If capacity is not a positive integer
*/
constructor(options) {
super();
this.buffer = [];
this.overflowHandlers = new Map();
if (!Number.isInteger(options.capacity) || options.capacity <= 0) {
throw new Error('Capacity must be a positive integer');
}
this.capacity = options.capacity;
this.overflowMode =
options.overflow === OverflowMode.EVICT
? OverflowMode.EVICT
: OverflowMode.REJECT;
this.initializeOverflowHandlers();
const handler = this.overflowHandlers.get(this.overflowMode);
if (!handler) {
throw new Error('Invalid overflow mode');
}
this.overflowHandler = handler;
}
/**
* Initializes handlers for different overflow modes
* @private
*/
initializeOverflowHandlers() {
this.overflowHandlers.set(OverflowMode.REJECT, (item) => {
this.emit('reject', item);
return false;
});
this.overflowHandlers.set(OverflowMode.EVICT, (item) => {
const evicted = this.buffer.shift();
if (evicted) {
this.emit('overflow', evicted);
}
return this.enqueue(item);
});
}
/**
* Adds an item to the buffer
* @param {T} item - Item to add
* @returns {boolean} True if item was added successfully, false otherwise
* @emits enqueue When item is added successfully
* @emits overflow When an item is evicted (in EVICT mode)
* @emits reject When item is rejected (in REJECT mode)
*/
enqueue(item) {
if (this.buffer.length < this.capacity) {
this.buffer.push(item);
this.emit('enqueue', item);
return true;
}
return this.overflowHandler(item);
}
/**
* Removes and returns the oldest item from the buffer
* @returns {T | undefined} The removed item, or undefined if buffer is empty
* @emits dequeue When an item is removed
*/
dequeue() {
if (this.buffer.length === 0) {
return undefined;
}
const item = this.buffer.shift();
if (item) {
this.emit('dequeue', item);
}
return item;
}
/**
* Checks if the buffer is at capacity
* @returns {boolean} True if buffer is full
*/
isFull() {
return this.buffer.length === this.capacity;
}
/**
* Checks if the buffer has no items
* @returns {boolean} True if buffer is empty
*/
isEmpty() {
return this.buffer.length === 0;
}
/**
* Gets the current number of items in the buffer
* @returns {number} Current buffer size
*/
size() {
return this.buffer.length;
}
/**
* Returns the oldest item without removing it
* @returns {T | undefined} The oldest item, or undefined if buffer is empty
*/
peek() {
return this.buffer[0];
}
/**
* Removes all items from the buffer
*/
clear() {
this.buffer = [];
}
/**
* Returns a copy of the buffer contents as an array
* @returns {T[]} Array containing buffer items in order
*/
toArray() {
return [...this.buffer];
}
}