import logger from "../utils/logger.js";
export interface ReconnectOptions {
maxAttempts: number;
initialDelayMs: number;
maxDelayMs: number;
}
export class ReconnectHandler {
private attempts = 0;
private readonly options: ReconnectOptions;
constructor(options: ReconnectOptions) {
this.options = options;
}
get canRetry(): boolean {
return this.attempts < this.options.maxAttempts;
}
get currentAttempt(): number {
return this.attempts;
}
reset(): void {
this.attempts = 0;
}
async waitForNext(serverId: string): Promise<void> {
if (!this.canRetry) {
throw new Error(`Max reconnect attempts (${this.options.maxAttempts}) reached for ${serverId}`);
}
const baseDelay = Math.min(
this.options.initialDelayMs * Math.pow(2, this.attempts),
this.options.maxDelayMs
);
// Add jitter: +/-25%
const jitter = baseDelay * 0.25 * (Math.random() * 2 - 1);
const delay = Math.max(0, Math.round(baseDelay + jitter));
this.attempts++;
logger.info(`Reconnecting to ${serverId}`, {
attempt: this.attempts,
maxAttempts: this.options.maxAttempts,
delayMs: delay,
});
await new Promise<void>((resolve) => setTimeout(resolve, delay));
}
}