Generic stream reconnection module that provides intelligent reconnection logic with configurable backoff strategies.
npx @tessl/cli install tessl/npm-reconnect-core@1.3.00
# Reconnect Core
1
2
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.
3
4
## Package Information
5
6
- **Package Name**: reconnect-core
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install reconnect-core`
10
11
## Core Imports
12
13
```javascript
14
const inject = require('reconnect-core');
15
```
16
17
For ES modules:
18
19
```javascript
20
import inject from 'reconnect-core';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const inject = require('reconnect-core');
27
const net = require('net');
28
29
// Create a TCP reconnection module
30
const reconnect = inject(function() {
31
// Arguments are passed from .connect() call
32
// 'this' refers to the reconnect emitter instance
33
return net.connect.apply(null, arguments);
34
});
35
36
// Create a reconnection instance
37
const connection = reconnect({
38
initialDelay: 1000,
39
maxDelay: 30000,
40
strategy: 'fibonacci'
41
}, function(stream) {
42
// Handle connected stream
43
console.log('Connected!');
44
stream.on('data', function(data) {
45
console.log('Received:', data.toString());
46
});
47
})
48
.on('connect', function(con) {
49
console.log('Connection established');
50
})
51
.on('reconnect', function(n, delay) {
52
console.log(`Reconnection attempt ${n}, delay: ${delay}ms`);
53
})
54
.on('disconnect', function(err) {
55
console.log('Disconnected:', err?.message);
56
})
57
.on('error', function(err) {
58
console.log('Connection error:', err.message);
59
});
60
61
// Start connecting
62
connection.connect(8080, 'localhost');
63
64
// Later: stop reconnecting
65
connection.disconnect();
66
```
67
68
## Architecture
69
70
Reconnect Core follows an injection pattern where users provide their own connection creation function. The module wraps this function with:
71
72
- **Backoff Strategy Integration**: Uses the `backoff` library for intelligent retry timing
73
- **Event-Driven Architecture**: Full EventEmitter interface for monitoring connection lifecycle
74
- **Connection State Management**: Tracks connection status and handles cleanup
75
- **Error Recovery**: Automatic reconnection with configurable failure limits
76
- **Flexible Configuration**: Support for multiple backoff strategies and custom options
77
78
## Capabilities
79
80
### Injection Function
81
82
The main export is a factory function that creates reconnection modules by injecting a connection creation function.
83
84
```javascript { .api }
85
/**
86
* Creates a reconnection module by injecting a connection creation function
87
* @param {Function} createConnection - Function that creates the underlying connection
88
* @returns {Function} Reconnection function that creates reconnection instances
89
*/
90
function inject(createConnection);
91
```
92
93
The `createConnection` function signature:
94
- Called with arguments passed to `.connect()` method
95
- Called with `this` bound to the reconnect emitter instance
96
- Must return a connection object that emits 'connect', 'close', 'end', and 'error' events
97
98
### Reconnection Function
99
100
The injected function returns a reconnection function that creates reconnection instances.
101
102
```javascript { .api }
103
/**
104
* Creates a reconnection instance with specified options and callback
105
* @param {Object|Function} opts - Configuration options or connection callback
106
* @param {Function} [onConnect] - Optional connection callback function
107
* @returns {ReconnectEmitter} EventEmitter instance with reconnection capabilities
108
*/
109
function reconnect(opts, onConnect);
110
```
111
112
### Configuration Options
113
114
```javascript { .api }
115
interface ReconnectOptions {
116
/** Initial delay before first reconnection attempt (default: 1000ms) */
117
initialDelay?: number;
118
/** Maximum delay between reconnection attempts (default: 30000ms) */
119
maxDelay?: number;
120
/** Backoff strategy: 'fibonacci', 'exponential', or custom backoff instance */
121
strategy?: string | BackoffStrategy;
122
/** Alias for strategy */
123
type?: string | BackoffStrategy;
124
/** Number of failed attempts before giving up (default: undefined/unlimited) */
125
failAfter?: number;
126
/** Randomization factor for backoff delays (0-1) */
127
randomisationFactor?: number;
128
/** Whether to treat connection as immediately connected (default: false) */
129
immediate?: boolean;
130
/** Alternative way to specify connection callback */
131
onConnect?: Function;
132
}
133
```
134
135
### Reconnect Emitter Instance
136
137
The reconnection function returns an EventEmitter instance with additional properties and methods.
138
139
```javascript { .api }
140
interface ReconnectEmitter extends EventEmitter {
141
/** Current connection state (read-only) */
142
connected: boolean;
143
/** Whether to continue reconnecting (read-write) */
144
reconnect: boolean;
145
/** Reference to current underlying connection (internal) */
146
_connection?: any;
147
148
/**
149
* Start connection/reconnection process
150
* @param {...any} args - Arguments passed to createConnection function
151
* @returns {ReconnectEmitter} Self for chaining
152
*/
153
connect(...args): ReconnectEmitter;
154
155
/**
156
* Alias for connect method
157
* @param {...any} args - Arguments passed to createConnection function
158
* @returns {ReconnectEmitter} Self for chaining
159
*/
160
listen(...args): ReconnectEmitter;
161
162
/**
163
* Stop reconnecting and end current connection
164
* @returns {ReconnectEmitter} Self for chaining
165
*/
166
disconnect(): ReconnectEmitter;
167
168
/**
169
* Reset backoff timer and attempt immediate reconnection
170
* @returns {undefined} No return value
171
*/
172
reset(): void;
173
}
174
```
175
176
### Events
177
178
The reconnect emitter instance emits the following events:
179
180
```javascript { .api }
181
// Connection established successfully
182
emitter.on('connect', (connection) => {});
183
emitter.on('connection', (connection) => {}); // Alias for 'connect'
184
185
// Before each reconnection attempt
186
emitter.on('reconnect', (attemptNumber, delay) => {});
187
188
// Connection lost or ended
189
emitter.on('disconnect', (error) => {});
190
191
// Connection error occurred
192
emitter.on('error', (error) => {});
193
194
// Backoff process events (from backoff library)
195
emitter.on('backoff', (attemptNumber, delay, error) => {});
196
197
// Maximum attempts reached, giving up
198
emitter.on('fail', (error) => {});
199
```
200
201
**Event Details:**
202
203
- **'connect'/'connection'**: Emitted when connection is successfully established
204
- `connection`: The underlying connection object returned by `createConnection`
205
206
- **'reconnect'**: Emitted before each reconnection attempt
207
- `attemptNumber`: Current attempt number (starts at 0)
208
- `delay`: Delay used before this attempt (in milliseconds)
209
210
- **'disconnect'**: Emitted when connection is lost or closed
211
- `error`: Optional error object if disconnection was due to an error
212
213
- **'error'**: Emitted when connection errors occur
214
- `error`: Error object describing the failure
215
216
- **'backoff'**: Emitted during backoff timing process
217
- `attemptNumber`: Current attempt number
218
- `delay`: Delay being used
219
- `error`: Error that triggered the backoff
220
221
- **'fail'**: Emitted when `failAfter` limit is reached
222
- `error`: Final error before giving up
223
224
### Backoff Strategies
225
226
Reconnect Core integrates with the `backoff` library and supports multiple strategies:
227
228
```javascript { .api }
229
// Built-in strategies (pass as string to 'strategy' option)
230
type BuiltInStrategy = 'fibonacci' | 'exponential';
231
232
// Custom backoff strategy interface
233
interface BackoffStrategy {
234
/** Calculate next delay value */
235
next(): number;
236
/** Reset the strategy to initial state */
237
reset(): void;
238
}
239
```
240
241
**Strategy Examples:**
242
243
```javascript
244
// Fibonacci backoff (default)
245
const connection = reconnect({ strategy: 'fibonacci' });
246
247
// Exponential backoff
248
const connection = reconnect({ strategy: 'exponential' });
249
250
// Custom strategy
251
const customStrategy = {
252
next: function() { return 5000; }, // Always 5 seconds
253
reset: function() { }
254
};
255
const connection = reconnect({
256
strategy: new (require('backoff')).Backoff(customStrategy)
257
});
258
```
259
260
## Usage Patterns
261
262
### TCP Reconnection
263
264
```javascript
265
const inject = require('reconnect-core');
266
const net = require('net');
267
268
const reconnect = inject(() => net.connect.apply(null, arguments));
269
const connection = reconnect().connect(8080, 'localhost');
270
```
271
272
### WebSocket Reconnection
273
274
```javascript
275
const inject = require('reconnect-core');
276
const WebSocket = require('ws');
277
278
const reconnect = inject((url) => new WebSocket(url));
279
const connection = reconnect({ immediate: true }, (ws) => {
280
ws.send('Hello Server!');
281
}).connect('ws://localhost:8080');
282
```
283
284
### HTTP Request Reconnection
285
286
```javascript
287
const inject = require('reconnect-core');
288
const http = require('http');
289
290
const reconnect = inject((options) => http.request(options));
291
const connection = reconnect({ immediate: true }, (req) => {
292
req.write('POST data');
293
req.end();
294
}).connect({ host: 'localhost', port: 8080, method: 'POST' });
295
```
296
297
### Advanced Configuration
298
299
```javascript
300
const connection = reconnect({
301
initialDelay: 500,
302
maxDelay: 60000,
303
strategy: 'exponential',
304
failAfter: 10,
305
randomisationFactor: 0.2,
306
immediate: false
307
}, function(stream) {
308
// Handle connection
309
})
310
.on('connect', (con) => console.log('Connected'))
311
.on('reconnect', (n, delay) => console.log(`Attempt ${n}, delay: ${delay}ms`))
312
.on('disconnect', (err) => console.log('Disconnected:', err?.message))
313
.on('fail', (err) => console.log('Max attempts reached, giving up'))
314
.connect(port, host);
315
316
// Manual control
317
setTimeout(() => {
318
connection.reconnect = false; // Disable auto-reconnection
319
connection.disconnect(); // Disconnect immediately
320
}, 30000);
321
322
// Force immediate reconnection
323
connection.reset();
324
```