or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

data-structures.mdindex.mdpool-lifecycle.mdpool-management.mdpool-monitoring.mdresource-operations.md
tile.json

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
    };
  }
}