feat(SmartsocketClient): Improve client reconnection logic with exponential backoff and jitter; update socket.io and @types/node dependencies
This commit is contained in:
parent
933f09d632
commit
da10b25214
103
changelog.md
Normal file
103
changelog.md
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-03-10 - 2.1.0 - feat(SmartsocketClient)
|
||||||
|
Improve client reconnection logic with exponential backoff and jitter; update socket.io and @types/node dependencies
|
||||||
|
|
||||||
|
- Bump engine.io from 6.5.4 to 6.6.4, socket.io and socket.io-client from 4.7.5 to 4.8.1
|
||||||
|
- Bump @types/node from ^20.12.7 to ^22.13.10
|
||||||
|
- Add new optional reconnection parameters (maxRetries, initialBackoffDelay, maxBackoffDelay) to SmartsocketClient options
|
||||||
|
- Implement exponential backoff with jitter for auto-reconnect and reset reconnection state on successful connection
|
||||||
|
|
||||||
|
## 2024-05-29 - 2.0.27 - docs
|
||||||
|
update description
|
||||||
|
|
||||||
|
## 2024-04-26 to 2024-03-30 - 2.0.26 … 2.0.24 - core & configuration
|
||||||
|
A series of internal fixes and configuration tweaks.
|
||||||
|
- fix(core): update
|
||||||
|
- update tsconfig
|
||||||
|
- update npmextra.json: githost
|
||||||
|
|
||||||
|
## 2023-09-10 to 2023-07-21 - 2.0.23 … 2.0.20 - core
|
||||||
|
Multiple minor core fixes were applied in rapid succession.
|
||||||
|
- fix(core): update
|
||||||
|
|
||||||
|
## 2023-07-21 to 2023-03-20 - 2.0.19 … 2.0.15 - core
|
||||||
|
Routine internal updates addressing core functionality.
|
||||||
|
- fix(core): update
|
||||||
|
|
||||||
|
## 2023-02-07 to 2022-03-24 - 2.0.14 … 2.0.0 - core
|
||||||
|
Further minor core updates were rolled out over several versions.
|
||||||
|
- fix(core): update
|
||||||
|
|
||||||
|
## 2022-03-14 - 1.2.22 - esm
|
||||||
|
A breaking change was introduced to switch the module system.
|
||||||
|
- BREAKING CHANGE(switch to esm): update
|
||||||
|
|
||||||
|
## 2022-01-20 to 2021-01-23 - 1.2.21 … 1.2.0 - core
|
||||||
|
A range of minor core fixes.
|
||||||
|
- fix(core): update
|
||||||
|
|
||||||
|
## 2020-12-26 - 1.1.71 - SmartsocketClient
|
||||||
|
New functionality in the socket client was added.
|
||||||
|
- feat(SmartsocketClient): socket client can now be stopped with .stop() in addition to .reconnect()
|
||||||
|
|
||||||
|
## 2020-12-26 to 2020-09-24 - 1.1.70 … 1.1.58 - core & test
|
||||||
|
A group of updates addressing both core mechanics and tests.
|
||||||
|
- fix(core): update
|
||||||
|
- fix(test): use @pushrocks/isohash instead of @pushrocks/smarthash
|
||||||
|
|
||||||
|
## 2019-11-08 to 2019-04-23 - 1.1.57 … 1.1.27 - core
|
||||||
|
Numerous versions in this period included only internal core fixes.
|
||||||
|
- fix(core): update
|
||||||
|
|
||||||
|
## 2019-01-31 to 2019-01-30 - 1.1.26 … 1.1.19 - build, docs & configuration
|
||||||
|
Updates went beyond the core, affecting build tooling and package metadata.
|
||||||
|
- fix(build): now building with tsbuild
|
||||||
|
- fix(readme): update
|
||||||
|
- fix(npmextra): adjust access level
|
||||||
|
- fix(scope): switch to @pushrocks
|
||||||
|
- fix(package.json): private setting
|
||||||
|
- fix(snyk): add .snyk file
|
||||||
|
- fix(structure): update to latest standards
|
||||||
|
|
||||||
|
## 2018-03-19 to 2018-03-15 - 1.1.18 … 1.1.12 - core & docs
|
||||||
|
Several improvements touching both functionality and documentation.
|
||||||
|
- now working as expected
|
||||||
|
- start transitioning to better SocketFunction handling
|
||||||
|
- add @types/node
|
||||||
|
- format and update README
|
||||||
|
- update to latest standards
|
||||||
|
|
||||||
|
## 2017-10-09 to 2017-07-07 - 1.1.11 … 1.1.07 - core & docs
|
||||||
|
Updates in this range improved both the internal mechanics and the developer‐facing materials.
|
||||||
|
- allow setting of specific server
|
||||||
|
- fix not ending error correctly
|
||||||
|
- update to newest version
|
||||||
|
- update docs and tests
|
||||||
|
- remove taskbuffer
|
||||||
|
- update to latest standards
|
||||||
|
|
||||||
|
## 2016-09-25 to 2016-09-03 - 1.1.6 … 1.1.3 - docs & core
|
||||||
|
Minor improvements in documentation and code quality.
|
||||||
|
- improve README
|
||||||
|
- added docs
|
||||||
|
- fix scoping of socket roles and perform small syntax fixes
|
||||||
|
|
||||||
|
## 2016-09-02 to 2016-08-16 - 1.1.2 … 1.1.1 - dependencies & security
|
||||||
|
Several housekeeping tasks to update dependencies and improve security.
|
||||||
|
- updated dependencies and exported socketConnection
|
||||||
|
- now authenticating sockets by checking the password hash
|
||||||
|
|
||||||
|
## 2016-08-15 - 1.1.0 - docs
|
||||||
|
A documentation update was published.
|
||||||
|
- update README
|
||||||
|
|
||||||
|
## 2016-08-15 - 1.0.7 - networking
|
||||||
|
A key update made the socket client work bi-directionally, enabling mesh setups.
|
||||||
|
- now working in both directions so mesh setups work
|
||||||
|
|
||||||
|
## 2016-08-14 to 2016-08-07 - 1.0.6 … 1.0.0 - internal changes
|
||||||
|
From the initial release onward, several internal improvements were introduced:
|
||||||
|
- updated tests and structure
|
||||||
|
- reworked reconnection logic and added a request/response abstraction for transparent function calls
|
||||||
|
- initial release features with updated documentation and structure
|
@ -33,9 +33,9 @@
|
|||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpromise": "^4.0.3",
|
||||||
"@push.rocks/smartrx": "^3.0.7",
|
"@push.rocks/smartrx": "^3.0.7",
|
||||||
"@push.rocks/smarttime": "^4.0.6",
|
"@push.rocks/smarttime": "^4.0.6",
|
||||||
"engine.io": "6.5.4",
|
"engine.io": "6.6.4",
|
||||||
"socket.io": "4.7.5",
|
"socket.io": "4.8.1",
|
||||||
"socket.io-client": "4.7.5"
|
"socket.io-client": "4.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.66",
|
"@git.zone/tsbuild": "^2.1.66",
|
||||||
@ -43,7 +43,7 @@
|
|||||||
"@git.zone/tsrun": "^1.2.44",
|
"@git.zone/tsrun": "^1.2.44",
|
||||||
"@git.zone/tstest": "^1.0.77",
|
"@git.zone/tstest": "^1.0.77",
|
||||||
"@push.rocks/tapbundle": "^5.0.23",
|
"@push.rocks/tapbundle": "^5.0.23",
|
||||||
"@types/node": "^20.12.7"
|
"@types/node": "^22.13.10"
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
"files": [
|
"files": [
|
||||||
|
11074
pnpm-lock.yaml
generated
11074
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartsocket',
|
name: '@push.rocks/smartsocket',
|
||||||
version: '2.0.27',
|
version: '2.1.0',
|
||||||
description: 'Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.'
|
description: 'Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.'
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,9 @@ export interface ISmartsocketClientOptions {
|
|||||||
url: string;
|
url: string;
|
||||||
alias: string; // an alias makes it easier to identify this client in a multo client environment
|
alias: string; // an alias makes it easier to identify this client in a multo client environment
|
||||||
autoReconnect?: boolean;
|
autoReconnect?: boolean;
|
||||||
|
maxRetries?: number; // maximum number of reconnection attempts
|
||||||
|
initialBackoffDelay?: number; // initial backoff delay in ms
|
||||||
|
maxBackoffDelay?: number; // maximum backoff delay in ms
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SmartsocketClient {
|
export class SmartsocketClient {
|
||||||
@ -32,6 +35,11 @@ export class SmartsocketClient {
|
|||||||
public serverUrl: string;
|
public serverUrl: string;
|
||||||
public serverPort: number;
|
public serverPort: number;
|
||||||
public autoReconnect: boolean;
|
public autoReconnect: boolean;
|
||||||
|
public maxRetries: number;
|
||||||
|
public initialBackoffDelay: number;
|
||||||
|
public maxBackoffDelay: number;
|
||||||
|
public currentRetryCount = 0;
|
||||||
|
public currentBackoffDelay: number;
|
||||||
|
|
||||||
// status handling
|
// status handling
|
||||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||||
@ -79,6 +87,10 @@ export class SmartsocketClient {
|
|||||||
this.serverUrl = optionsArg.url;
|
this.serverUrl = optionsArg.url;
|
||||||
this.serverPort = optionsArg.port;
|
this.serverPort = optionsArg.port;
|
||||||
this.autoReconnect = optionsArg.autoReconnect;
|
this.autoReconnect = optionsArg.autoReconnect;
|
||||||
|
this.maxRetries = optionsArg.maxRetries ?? 100; // Default to 100 retries
|
||||||
|
this.initialBackoffDelay = optionsArg.initialBackoffDelay ?? 1000; // Default to 1 second
|
||||||
|
this.maxBackoffDelay = optionsArg.maxBackoffDelay ?? 60000; // Default to 1 minute
|
||||||
|
this.currentBackoffDelay = this.initialBackoffDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
public addSocketFunction(socketFunction: SocketFunction<any>) {
|
||||||
@ -89,6 +101,10 @@ export class SmartsocketClient {
|
|||||||
* connect the client to the server
|
* connect the client to the server
|
||||||
*/
|
*/
|
||||||
public async connect() {
|
public async connect() {
|
||||||
|
// Reset retry counters on new connection attempt
|
||||||
|
this.currentRetryCount = 0;
|
||||||
|
this.currentBackoffDelay = this.initialBackoffDelay;
|
||||||
|
|
||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
const smartenvInstance = new plugins.smartenv.Smartenv();
|
const smartenvInstance = new plugins.smartenv.Smartenv();
|
||||||
const socketIoClient: any = await smartenvInstance.getEnvAwareModule({
|
const socketIoClient: any = await smartenvInstance.getEnvAwareModule({
|
||||||
@ -216,8 +232,27 @@ export class SmartsocketClient {
|
|||||||
|
|
||||||
if (this.autoReconnect && useAutoReconnectSetting && this.eventStatus !== 'connecting') {
|
if (this.autoReconnect && useAutoReconnectSetting && this.eventStatus !== 'connecting') {
|
||||||
this.updateStatus('connecting');
|
this.updateStatus('connecting');
|
||||||
console.log('debounced reconnect!');
|
|
||||||
await plugins.smartdelay.delayForRandom(10000, 20000);
|
// Check if we've exceeded the maximum number of retries
|
||||||
|
if (this.currentRetryCount >= this.maxRetries) {
|
||||||
|
logger.log('warn', `Maximum reconnection attempts (${this.maxRetries}) reached. Giving up.`);
|
||||||
|
this.disconnectRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment retry counter
|
||||||
|
this.currentRetryCount++;
|
||||||
|
|
||||||
|
// Calculate backoff with jitter (±20% randomness)
|
||||||
|
const jitter = this.currentBackoffDelay * 0.2 * (Math.random() * 2 - 1);
|
||||||
|
const delay = Math.min(this.currentBackoffDelay + jitter, this.maxBackoffDelay);
|
||||||
|
|
||||||
|
logger.log('info', `Reconnect attempt ${this.currentRetryCount}/${this.maxRetries} in ${Math.round(delay)}ms`);
|
||||||
|
|
||||||
|
// Apply exponential backoff for next time (doubling with each attempt)
|
||||||
|
this.currentBackoffDelay = Math.min(this.currentBackoffDelay * 2, this.maxBackoffDelay);
|
||||||
|
|
||||||
|
await plugins.smartdelay.delayFor(delay);
|
||||||
this.disconnectRunning = false;
|
this.disconnectRunning = false;
|
||||||
await this.connect();
|
await this.connect();
|
||||||
} else {
|
} else {
|
||||||
@ -230,6 +265,8 @@ export class SmartsocketClient {
|
|||||||
*/
|
*/
|
||||||
public async stop() {
|
public async stop() {
|
||||||
this.autoReconnect = false;
|
this.autoReconnect = false;
|
||||||
|
this.currentRetryCount = 0;
|
||||||
|
this.currentBackoffDelay = this.initialBackoffDelay;
|
||||||
await this.disconnect();
|
await this.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,5 +299,19 @@ export class SmartsocketClient {
|
|||||||
this.eventSubject.next(statusArg);
|
this.eventSubject.next(statusArg);
|
||||||
}
|
}
|
||||||
this.eventStatus = statusArg;
|
this.eventStatus = statusArg;
|
||||||
|
|
||||||
|
// Reset reconnection state when connection is successful
|
||||||
|
if (statusArg === 'connected') {
|
||||||
|
this.currentRetryCount = 0;
|
||||||
|
this.currentBackoffDelay = this.initialBackoffDelay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the reconnection state
|
||||||
|
*/
|
||||||
|
public resetReconnectionState() {
|
||||||
|
this.currentRetryCount = 0;
|
||||||
|
this.currentBackoffDelay = this.initialBackoffDelay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user