feat(SmartsocketClient): Improve client reconnection logic with exponential backoff and jitter; update socket.io and @types/node dependencies
This commit is contained in:
		| @@ -1,8 +1,8 @@ | ||||
| /** | ||||
|  * autocreated commitinfo by @pushrocks/commitinfo | ||||
|  * autocreated commitinfo by @push.rocks/commitinfo | ||||
|  */ | ||||
| export const commitinfo = { | ||||
|   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.' | ||||
| } | ||||
|   | ||||
| @@ -18,6 +18,9 @@ export interface ISmartsocketClientOptions { | ||||
|   url: string; | ||||
|   alias: string; // an alias makes it easier to identify this client in a multo client environment | ||||
|   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 { | ||||
| @@ -32,6 +35,11 @@ export class SmartsocketClient { | ||||
|   public serverUrl: string; | ||||
|   public serverPort: number; | ||||
|   public autoReconnect: boolean; | ||||
|   public maxRetries: number; | ||||
|   public initialBackoffDelay: number; | ||||
|   public maxBackoffDelay: number; | ||||
|   public currentRetryCount = 0; | ||||
|   public currentBackoffDelay: number; | ||||
|  | ||||
|   // status handling | ||||
|   public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>(); | ||||
| @@ -79,6 +87,10 @@ export class SmartsocketClient { | ||||
|     this.serverUrl = optionsArg.url; | ||||
|     this.serverPort = optionsArg.port; | ||||
|     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>) { | ||||
| @@ -89,6 +101,10 @@ export class SmartsocketClient { | ||||
|    * connect the client to the server | ||||
|    */ | ||||
|   public async connect() { | ||||
|     // Reset retry counters on new connection attempt | ||||
|     this.currentRetryCount = 0; | ||||
|     this.currentBackoffDelay = this.initialBackoffDelay; | ||||
|      | ||||
|     const done = plugins.smartpromise.defer(); | ||||
|     const smartenvInstance = new plugins.smartenv.Smartenv(); | ||||
|     const socketIoClient: any = await smartenvInstance.getEnvAwareModule({ | ||||
| @@ -216,8 +232,27 @@ export class SmartsocketClient { | ||||
|  | ||||
|     if (this.autoReconnect && useAutoReconnectSetting && this.eventStatus !== '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; | ||||
|       await this.connect(); | ||||
|     } else { | ||||
| @@ -230,6 +265,8 @@ export class SmartsocketClient { | ||||
|    */ | ||||
|   public async stop() { | ||||
|     this.autoReconnect = false; | ||||
|     this.currentRetryCount = 0; | ||||
|     this.currentBackoffDelay = this.initialBackoffDelay; | ||||
|     await this.disconnect(); | ||||
|   } | ||||
|  | ||||
| @@ -262,5 +299,19 @@ export class SmartsocketClient { | ||||
|       this.eventSubject.next(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; | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user