diff --git a/src/core/engines/noweb/session.noweb.core.ts b/src/core/engines/noweb/session.noweb.core.ts index b79ef368..cbf6dad2 100644 --- a/src/core/engines/noweb/session.noweb.core.ts +++ b/src/core/engines/noweb/session.noweb.core.ts @@ -154,6 +154,7 @@ import { sleep, waitUntil } from '@waha/utils/promiseTimeout'; import { exclude } from '@waha/utils/reactive/ops/exclude'; import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner'; import { SinglePeriodicJobRunner } from '@waha/utils/SinglePeriodicJobRunner'; +import { StatusTracker } from '@waha/utils/StatusTracker'; import * as Buffer from 'buffer'; import { Agent } from 'https'; import * as lodash from 'lodash'; @@ -216,6 +217,8 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { store: INowebStore; private qr: QR; + private statusTracker = new StatusTracker(); + public constructor(config) { super(config); this.shouldRestart = true; @@ -254,6 +257,15 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { this.authNOWEBStore = null; } + protected set status(value: WAHASessionStatus) { + this.statusTracker.track(value); + super.status = value; + } + + public get status() { + return super.status; + } + async start() { this.status = WAHASessionStatus.STARTING; await this.buildClient().catch((err) => { @@ -419,6 +431,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { ); return; } + this.startDelayedJob.schedule(async () => { if (!this.shouldRestart) { this.logger.warn( @@ -443,12 +456,20 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { this.resubscribeToKnownPresences(); return; } else if (connection === 'close') { + if (this.statusTracker.isStuckInStarting()) { + this.logger.error( + 'Session stuck in STARTING status, force stopping the session.', + ); + await this.failed(); + return; + } + + // reconnect if not logged out const shouldReconnect = // @ts-ignore: Property output does not exist on type 'Error' lastDisconnect.error?.output?.statusCode !== DisconnectReason.loggedOut; this.qr.save(''); - // reconnect if not logged out if (shouldReconnect) { if (lastDisconnect.error) { this.logger.info( diff --git a/src/utils/StatusTracker.ts b/src/utils/StatusTracker.ts new file mode 100644 index 00000000..039a877e --- /dev/null +++ b/src/utils/StatusTracker.ts @@ -0,0 +1,25 @@ +import { WAHASessionStatus } from '../structures/enums.dto'; + +const STUCK_IN_STARTING_THRESHOLD = 20; + +/** + * Keeps track of session statuses (with timestamps) for the last `trackPeriodMs` milliseconds. + */ +export class StatusTracker { + private numberOfStarting: number = 0; + + public track(status: WAHASessionStatus): void { + if (status == WAHASessionStatus.STARTING) { + this.numberOfStarting += 1; + } else { + this.numberOfStarting = 0; + } + } + + /** + * Checks if the session has been continuously 'STARTING' + */ + public isStuckInStarting(): boolean { + return this.numberOfStarting >= STUCK_IN_STARTING_THRESHOLD; + } +}