or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-reconnect-core

Generic stream reconnection module that provides intelligent reconnection logic with configurable backoff strategies.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/reconnect-core@1.3.x

To install, run

npx @tessl/cli install tessl/npm-reconnect-core@1.3.0

index.mddocs/

Reconnect Core

Reconnect Core is a generic stream reconnection module that provides intelligent reconnection logic with configurable backoff strategies. It serves as a foundation for building specialized reconnection libraries for TCP, WebSocket, and other network protocols, handling connection state management and automatic reconnection with robust error handling.

Package Information

  • Package Name: reconnect-core
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install reconnect-core

Core Imports

const inject = require('reconnect-core');

For ES modules:

import inject from 'reconnect-core';

Basic Usage

const inject = require('reconnect-core');
const net = require('net');

// Create a TCP reconnection module
const reconnect = inject(function() {
  // Arguments are passed from .connect() call
  // 'this' refers to the reconnect emitter instance
  return net.connect.apply(null, arguments);
});

// Create a reconnection instance
const connection = reconnect({
  initialDelay: 1000,
  maxDelay: 30000,
  strategy: 'fibonacci'
}, function(stream) {
  // Handle connected stream
  console.log('Connected!');
  stream.on('data', function(data) {
    console.log('Received:', data.toString());
  });
})
.on('connect', function(con) {
  console.log('Connection established');
})
.on('reconnect', function(n, delay) {
  console.log(`Reconnection attempt ${n}, delay: ${delay}ms`);
})
.on('disconnect', function(err) {
  console.log('Disconnected:', err?.message);
})
.on('error', function(err) {
  console.log('Connection error:', err.message);
});

// Start connecting
connection.connect(8080, 'localhost');

// Later: stop reconnecting
connection.disconnect();

Architecture

Reconnect Core follows an injection pattern where users provide their own connection creation function. The module wraps this function with:

  • Backoff Strategy Integration: Uses the backoff library for intelligent retry timing
  • Event-Driven Architecture: Full EventEmitter interface for monitoring connection lifecycle
  • Connection State Management: Tracks connection status and handles cleanup
  • Error Recovery: Automatic reconnection with configurable failure limits
  • Flexible Configuration: Support for multiple backoff strategies and custom options

Capabilities

Injection Function

The main export is a factory function that creates reconnection modules by injecting a connection creation function.

/**
 * Creates a reconnection module by injecting a connection creation function
 * @param {Function} createConnection - Function that creates the underlying connection
 * @returns {Function} Reconnection function that creates reconnection instances
 */
function inject(createConnection);

The createConnection function signature:

  • Called with arguments passed to .connect() method
  • Called with this bound to the reconnect emitter instance
  • Must return a connection object that emits 'connect', 'close', 'end', and 'error' events

Reconnection Function

The injected function returns a reconnection function that creates reconnection instances.

/**
 * Creates a reconnection instance with specified options and callback
 * @param {Object|Function} opts - Configuration options or connection callback
 * @param {Function} [onConnect] - Optional connection callback function
 * @returns {ReconnectEmitter} EventEmitter instance with reconnection capabilities
 */
function reconnect(opts, onConnect);

Configuration Options

interface ReconnectOptions {
  /** Initial delay before first reconnection attempt (default: 1000ms) */
  initialDelay?: number;
  /** Maximum delay between reconnection attempts (default: 30000ms) */
  maxDelay?: number;
  /** Backoff strategy: 'fibonacci', 'exponential', or custom backoff instance */
  strategy?: string | BackoffStrategy;
  /** Alias for strategy */
  type?: string | BackoffStrategy;
  /** Number of failed attempts before giving up (default: undefined/unlimited) */
  failAfter?: number;
  /** Randomization factor for backoff delays (0-1) */
  randomisationFactor?: number;
  /** Whether to treat connection as immediately connected (default: false) */
  immediate?: boolean;
  /** Alternative way to specify connection callback */
  onConnect?: Function;
}

Reconnect Emitter Instance

The reconnection function returns an EventEmitter instance with additional properties and methods.

interface ReconnectEmitter extends EventEmitter {
  /** Current connection state (read-only) */
  connected: boolean;
  /** Whether to continue reconnecting (read-write) */
  reconnect: boolean;
  /** Reference to current underlying connection (internal) */
  _connection?: any;
  
  /**
   * Start connection/reconnection process
   * @param {...any} args - Arguments passed to createConnection function
   * @returns {ReconnectEmitter} Self for chaining
   */
  connect(...args): ReconnectEmitter;
  
  /**
   * Alias for connect method
   * @param {...any} args - Arguments passed to createConnection function
   * @returns {ReconnectEmitter} Self for chaining
   */
  listen(...args): ReconnectEmitter;
  
  /**
   * Stop reconnecting and end current connection
   * @returns {ReconnectEmitter} Self for chaining
   */
  disconnect(): ReconnectEmitter;
  
  /**
   * Reset backoff timer and attempt immediate reconnection
   * @returns {undefined} No return value
   */
  reset(): void;
}

Events

The reconnect emitter instance emits the following events:

// Connection established successfully
emitter.on('connect', (connection) => {});
emitter.on('connection', (connection) => {}); // Alias for 'connect'

// Before each reconnection attempt
emitter.on('reconnect', (attemptNumber, delay) => {});

// Connection lost or ended
emitter.on('disconnect', (error) => {});

// Connection error occurred
emitter.on('error', (error) => {});

// Backoff process events (from backoff library)
emitter.on('backoff', (attemptNumber, delay, error) => {});

// Maximum attempts reached, giving up
emitter.on('fail', (error) => {});

Event Details:

  • 'connect'/'connection': Emitted when connection is successfully established

    • connection: The underlying connection object returned by createConnection
  • 'reconnect': Emitted before each reconnection attempt

    • attemptNumber: Current attempt number (starts at 0)
    • delay: Delay used before this attempt (in milliseconds)
  • 'disconnect': Emitted when connection is lost or closed

    • error: Optional error object if disconnection was due to an error
  • 'error': Emitted when connection errors occur

    • error: Error object describing the failure
  • 'backoff': Emitted during backoff timing process

    • attemptNumber: Current attempt number
    • delay: Delay being used
    • error: Error that triggered the backoff
  • 'fail': Emitted when failAfter limit is reached

    • error: Final error before giving up

Backoff Strategies

Reconnect Core integrates with the backoff library and supports multiple strategies:

// Built-in strategies (pass as string to 'strategy' option)
type BuiltInStrategy = 'fibonacci' | 'exponential';

// Custom backoff strategy interface
interface BackoffStrategy {
  /** Calculate next delay value */
  next(): number;
  /** Reset the strategy to initial state */
  reset(): void;
}

Strategy Examples:

// Fibonacci backoff (default)
const connection = reconnect({ strategy: 'fibonacci' });

// Exponential backoff
const connection = reconnect({ strategy: 'exponential' });

// Custom strategy
const customStrategy = {
  next: function() { return 5000; }, // Always 5 seconds
  reset: function() { }
};
const connection = reconnect({ 
  strategy: new (require('backoff')).Backoff(customStrategy)
});

Usage Patterns

TCP Reconnection

const inject = require('reconnect-core');
const net = require('net');

const reconnect = inject(() => net.connect.apply(null, arguments));
const connection = reconnect().connect(8080, 'localhost');

WebSocket Reconnection

const inject = require('reconnect-core');
const WebSocket = require('ws');

const reconnect = inject((url) => new WebSocket(url));
const connection = reconnect({ immediate: true }, (ws) => {
  ws.send('Hello Server!');
}).connect('ws://localhost:8080');

HTTP Request Reconnection

const inject = require('reconnect-core');
const http = require('http');

const reconnect = inject((options) => http.request(options));
const connection = reconnect({ immediate: true }, (req) => {
  req.write('POST data');
  req.end();
}).connect({ host: 'localhost', port: 8080, method: 'POST' });

Advanced Configuration

const connection = reconnect({
  initialDelay: 500,
  maxDelay: 60000,
  strategy: 'exponential',
  failAfter: 10,
  randomisationFactor: 0.2,
  immediate: false
}, function(stream) {
  // Handle connection
})
.on('connect', (con) => console.log('Connected'))
.on('reconnect', (n, delay) => console.log(`Attempt ${n}, delay: ${delay}ms`))
.on('disconnect', (err) => console.log('Disconnected:', err?.message))
.on('fail', (err) => console.log('Max attempts reached, giving up'))
.connect(port, host);

// Manual control
setTimeout(() => {
  connection.reconnect = false; // Disable auto-reconnection
  connection.disconnect();      // Disconnect immediately
}, 30000);

// Force immediate reconnection
connection.reset();