Idle timeout

This commit is contained in:
Adhiraj
2020-09-18 16:22:57 +05:30
parent 7eb454b3dd
commit b7de86afce
4 changed files with 26 additions and 10 deletions

View File

@@ -45,6 +45,7 @@ export class WAConnection extends EventEmitter {
regenerateQRIntervalMs = 30*1000
connectOptions: WAConnectOptions = {
timeoutMs: 60*1000,
maxIdleTimeMs: 10*1000,
waitForChats: true,
maxRetries: 5,
connectCooldownMs: 2250,
@@ -80,6 +81,7 @@ export class WAConnection extends EventEmitter {
protected lastDisconnectReason: DisconnectReason
protected mediaConn: MediaConnInfo
protected debounceTimeout: NodeJS.Timeout
constructor () {
super ()
@@ -101,7 +103,10 @@ export class WAConnection extends EventEmitter {
error !== DisconnectReason.invalidSession // do not reconnect if credentials have been invalidated
this.closeInternal(error, willReconnect)
willReconnect && this.connect ()
willReconnect && (
this.connect ()
.catch(err => {}) // prevent unhandled exeception
)
}
/**
* base 64 encode the authentication credentials and return them
@@ -316,6 +321,7 @@ export class WAConnection extends EventEmitter {
this.qrTimeout && clearTimeout (this.qrTimeout)
this.keepAliveReq && clearInterval(this.keepAliveReq)
this.debounceTimeout && clearTimeout (this.debounceTimeout)
this.state = 'close'
this.msgCount = 0

View File

@@ -6,7 +6,7 @@ import { MessageLogLevel, WAMetric, WAFlag, BaileysError, Presence, WAUser } fro
export class WAConnection extends Base {
/** Authenticate the connection */
protected async authenticate (reconnect?: string) {
protected async authenticate (onConnectionValidated: () => void, reconnect?: string) {
// if no auth info is present, that is, a new session has to be established
// generate a client ID
if (!this.authInfo?.clientID) {
@@ -56,9 +56,9 @@ export class WAConnection extends Base {
}
const validationJSON = (await Promise.all (initQueries)).slice(-1)[0] // get the last result
this.user = await this.validateNewConnection(validationJSON[1]) // validate the connection
onConnectionValidated ()
this.log('validated connection successfully', MessageLogLevel.info)
const response = await this.query({ json: ['query', 'ProfilePicThumb', this.user.jid], waitForOpen: false, expect200: false })

View File

@@ -68,13 +68,18 @@ export class WAConnection extends Base {
let cancel: () => void
const task = Utils.promiseTimeout(timeoutMs, (resolve, reject) => {
let task: Promise<any> = Promise.resolve ()
const checkIdleTime = () => {
this.debounceTimeout && clearTimeout (this.debounceTimeout)
this.debounceTimeout = setTimeout (() => rejectSafe (TimedOutError()), this.connectOptions.maxIdleTimeMs)
}
const debouncedTimeout = () => this.connectOptions.maxIdleTimeMs && this.conn.addEventListener ('message', checkIdleTime)
// add wait for chats promise if required
if (typeof options?.waitForChats === 'undefined' ? true : options?.waitForChats) {
const {waitForChats, cancelChats} = this.receiveChatsAndContacts()
task = waitForChats
cancel = cancelChats
}
// determine whether reconnect should be used or not
const shouldUseReconnect = this.lastDisconnectReason !== DisconnectReason.replaced &&
this.lastDisconnectReason !== DisconnectReason.unknown &&
@@ -83,16 +88,17 @@ export class WAConnection extends Base {
const reconnectID = shouldUseReconnect ? this.user.jid.replace ('@s.whatsapp.net', '@c.us') : null
this.conn = new WS(WS_URL, null, { origin: DEFAULT_ORIGIN, timeout: timeoutMs, agent: options.agent })
this.conn.on('message', data => this.onMessageRecieved(data as any))
this.conn = new WS(WS_URL, null, { origin: DEFAULT_ORIGIN, timeout: this.connectOptions.maxIdleTimeMs, agent: options.agent })
this.conn.addEventListener('message', ({data}) => this.onMessageRecieved(data as any))
this.conn.on ('open', async () => {
this.log(`connected to WhatsApp Web server, authenticating via ${reconnectID ? 'reconnect' : 'takeover'}`, MessageLogLevel.info)
try {
task = Promise.all ([
task,
this.authenticate (reconnectID)
// debounce the timeout once validated
this.authenticate (debouncedTimeout, reconnectID)
.then (
() => {
this.conn
@@ -102,12 +108,14 @@ export class WAConnection extends Base {
)
])
const [result] = await task
this.conn.removeEventListener ('message', checkIdleTime)
resolve (result)
} catch (error) {
reject (error)
}
})
const rejectSafe = error => {
task = task.catch (() => {})
reject (error)
@@ -138,7 +146,7 @@ export class WAConnection extends Base {
const result = connect ()
cancellations.push (result.cancel)
const final = await result.promise
const final = await result.promise
return final
} catch (error) {
this.endConnection ()

View File

@@ -67,6 +67,8 @@ export enum ReconnectMode {
export type WAConnectOptions = {
/** timeout after which the connect attempt will fail, set to null for default timeout value */
timeoutMs?: number
/** */
maxIdleTimeMs?: number
/** maximum attempts to connect */
maxRetries?: number
/** should the chats be waited for */