CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-generic-pool

Generic resource pooling for Node.js applications with Promise-based API for efficient management of expensive resources.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

data-structures.mddocs/

Data Structures

Utility data structures used internally by the pool, also available for external use including double-ended queues and priority queues for advanced resource management scenarios.

Capabilities

Deque (Double-Ended Queue)

A double-ended queue implementation backed by a doubly-linked list, supporting efficient insertion and removal from both ends.

/**
 * Double-ended queue with efficient operations at both ends
 */
class Deque {
  constructor();
  
  /** Removes and returns the first element */
  shift(): any;
  
  /** Adds element to the beginning */
  unshift(element: any): void;
  
  /** Adds element to the end */
  push(element: any): void;
  
  /** Removes and returns the last element */
  pop(): any;
  
  /** Returns iterator for forward traversal */
  iterator(): DequeIterator;
  
  /** Returns iterator for reverse traversal */
  reverseIterator(): DequeIterator;
  
  /** ES6 iterator support */
  [Symbol.iterator](): DequeIterator;
  
  /** Reference to first element without removing */
  readonly head: any;
  
  /** Reference to last element without removing */
  readonly tail: any;
  
  /** Number of elements in the deque */
  readonly length: number;
}

Usage Examples:

const { Deque } = require('generic-pool');

// Create and use deque
const queue = new Deque();

// Add elements
queue.push('first');
queue.push('second');
queue.unshift('before-first');

console.log(queue.length); // 3
console.log(queue.head);   // 'before-first'
console.log(queue.tail);   // 'second'

// Remove elements
const first = queue.shift(); // 'before-first'
const last = queue.pop();    // 'second'

// Iteration
queue.push('a', 'b', 'c');
for (const item of queue) {
  console.log(item); // 'a', 'b', 'c'
}

// Manual iteration
const iterator = queue.iterator();
let current = iterator.next();
while (!current.done) {
  console.log(current.value);
  current = iterator.next();
}

// Reverse iteration
const reverseIter = queue.reverseIterator();
let reverseCurrent = reverseIter.next();
while (!reverseCurrent.done) {
  console.log(reverseCurrent.value);
  reverseCurrent = reverseIter.next();
}

PriorityQueue

A priority queue implementation that manages multiple priority levels, with higher priority items dequeued first.

/**
 * Priority queue with configurable priority levels
 */
class PriorityQueue {
  /**
   * Creates a priority queue
   * @param size - Number of priority levels (higher number = more levels)
   */
  constructor(size: number);
  
  /**
   * Adds an item with specified priority
   * @param obj - Item to add
   * @param priority - Priority level (0 = highest priority)
   */
  enqueue(obj: any, priority: number): void;
  
  /** Removes and returns the highest priority item */
  dequeue(): any;
  
  /** Total number of items across all priority levels */
  readonly length: number;
  
  /** Reference to highest priority item without removing */
  readonly head: any;
  
  /** Reference to lowest priority item without removing */
  readonly tail: any;
}

Usage Examples:

const { PriorityQueue } = require('generic-pool');

// Create priority queue with 3 levels (0=high, 1=medium, 2=low)
const pqueue = new PriorityQueue(3);

// Add items with different priorities
pqueue.enqueue('low-priority-task', 2);
pqueue.enqueue('high-priority-task', 0);
pqueue.enqueue('medium-priority-task', 1);
pqueue.enqueue('another-high-priority', 0);

console.log(pqueue.length); // 4

// Dequeue items (highest priority first)
console.log(pqueue.dequeue()); // 'high-priority-task'
console.log(pqueue.dequeue()); // 'another-high-priority'
console.log(pqueue.dequeue()); // 'medium-priority-task'
console.log(pqueue.dequeue()); // 'low-priority-task'

// Priority boundaries
const workQueue = new PriorityQueue(5);

// Out-of-range priorities get clamped
workQueue.enqueue('task1', -1);  // Becomes priority 0 (highest)
workQueue.enqueue('task2', 10);  // Becomes priority 4 (lowest)
workQueue.enqueue('task3', 2);   // Stays priority 2

// Task scheduling example
class TaskScheduler {
  constructor() {
    this.queue = new PriorityQueue(3);
    this.processing = false;
  }
  
  addTask(task, priority = 2) {
    this.queue.enqueue(task, priority);
    this.processNext();
  }
  
  async processNext() {
    if (this.processing || this.queue.length === 0) return;
    
    this.processing = true;
    const task = this.queue.dequeue();
    
    try {
      await task.execute();
    } catch (error) {
      console.error('Task failed:', error);
    }
    
    this.processing = false;
    
    // Process next task if available
    if (this.queue.length > 0) {
      setImmediate(() => this.processNext());
    }
  }
}

DefaultEvictor

Default resource eviction strategy for determining when idle resources should be removed from the pool.

/**
 * Default eviction strategy for pool resources
 */
class DefaultEvictor {
  /**
   * Determines if a resource should be evicted
   * @param config - Pool configuration object
   * @param pooledResource - Resource wrapper with timing information
   * @param availableObjectsCount - Current number of available resources
   * @returns true if resource should be evicted, false otherwise
   */
  evict(config: any, pooledResource: any, availableObjectsCount: number): boolean;
}

Usage Examples:

const { DefaultEvictor } = require('generic-pool');

// Custom pool with custom evictor
class CustomEvictor {
  evict(config, pooledResource, availableObjectsCount) {
    const idleTime = Date.now() - pooledResource.lastIdleTime;
    
    // Custom eviction logic
    if (idleTime > 60000 && availableObjectsCount > config.min) {
      return true; // Evict resources idle for more than 1 minute
    }
    
    return false;
  }
}

// Use custom evictor with pool
const { Pool, Deque, PriorityQueue } = require('generic-pool');

const customPool = new Pool(
  CustomEvictor,
  Deque,
  PriorityQueue,
  factory,
  options
);

// Eviction monitoring
class EvictionMonitor extends DefaultEvictor {
  constructor() {
    super();
    this.evictionCount = 0;
    this.evictionHistory = [];
  }
  
  evict(config, pooledResource, availableObjectsCount) {
    const shouldEvict = super.evict(config, pooledResource, availableObjectsCount);
    
    if (shouldEvict) {
      this.evictionCount++;
      this.evictionHistory.push({
        timestamp: Date.now(),
        idleTime: Date.now() - pooledResource.lastIdleTime,
        availableCount: availableObjectsCount
      });
      
      // Keep only last 100 evictions
      if (this.evictionHistory.length > 100) {
        this.evictionHistory.shift();
      }
      
      console.log(`Resource evicted (total: ${this.evictionCount})`);
    }
    
    return shouldEvict;
  }
  
  getStats() {
    return {
      totalEvictions: this.evictionCount,
      recentEvictions: this.evictionHistory.length,
      averageIdleTime: this.evictionHistory.reduce((sum, e) => sum + e.idleTime, 0) / this.evictionHistory.length
    };
  }
}

Iterator Support

Both Deque and the internal data structures provide comprehensive iterator support for traversal.

Usage Examples:

const { Deque } = require('generic-pool');

const queue = new Deque();
queue.push('a', 'b', 'c', 'd');

// ES6 for...of iteration
for (const item of queue) {
  console.log(item); // 'a', 'b', 'c', 'd'
}

// Array spread operator
const items = [...queue]; // ['a', 'b', 'c', 'd']

// Manual iterator usage
const iterator = queue.iterator();
let result = iterator.next();

while (!result.done) {
  console.log(result.value);
  result = iterator.next();
}

// Reverse iteration
const reverseIterator = queue.reverseIterator();
const reverseItems = [];

let reverseResult = reverseIterator.next();
while (!reverseResult.done) {
  reverseItems.push(reverseResult.value);
  reverseResult = reverseIterator.next();
}

console.log(reverseItems); // ['d', 'c', 'b', 'a']

// Iterator with external state
function processQueueWithState(queue) {
  const iterator = queue.iterator();
  let index = 0;
  
  return {
    next() {
      const result = iterator.next();
      if (!result.done) {
        return {
          index: index++,
          value: result.value,
          done: false
        };
      }
      return { done: true };
    }
  };
}

const processor = processQueueWithState(queue);
let processed = processor.next();
while (!processed.done) {
  console.log(`Item ${processed.index}: ${processed.value}`);
  processed = processor.next();
}

External Usage Patterns

Using the data structures outside of the pool context for custom applications.

Usage Examples:

const { Deque, PriorityQueue } = require('generic-pool');

// Custom buffer implementation
class CircularBuffer {
  constructor(maxSize) {
    this.buffer = new Deque();
    this.maxSize = maxSize;
  }
  
  add(item) {
    if (this.buffer.length >= this.maxSize) {
      this.buffer.shift(); // Remove oldest
    }
    this.buffer.push(item);
  }
  
  getAll() {
    return [...this.buffer];
  }
  
  getLatest(count) {
    const items = [];
    const iterator = this.buffer.reverseIterator();
    let result = iterator.next();
    
    while (!result.done && items.length < count) {
      items.push(result.value);
      result = iterator.next();
    }
    
    return items;
  }
}

// Request queue with priority handling
class RequestQueue {
  constructor() {
    this.queue = new PriorityQueue(3); // High, medium, low
    this.processing = false;
  }
  
  addRequest(request, priority = 2) {
    this.queue.enqueue({
      id: Math.random().toString(36),
      request,
      timestamp: Date.now(),
      priority
    }, priority);
    
    this.processQueue();
  }
  
  async processQueue() {
    if (this.processing) return;
    
    this.processing = true;
    
    while (this.queue.length > 0) {
      const item = this.queue.dequeue();
      console.log(`Processing request ${item.id} (priority ${item.priority})`);
      
      try {
        await this.handleRequest(item.request);
      } catch (error) {
        console.error(`Request ${item.id} failed:`, error);
      }
    }
    
    this.processing = false;
  }
  
  async handleRequest(request) {
    // Simulate request processing
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  getQueueStatus() {
    return {
      pending: this.queue.length,
      processing: this.processing,
      nextPriority: this.queue.head ? this.queue.head.priority : null
    };
  }
}

docs

data-structures.md

index.md

pool-lifecycle.md

pool-management.md

pool-monitoring.md

resource-operations.md

tile.json