connect cooldown + terminate WS instead of close

This commit is contained in:
Adhiraj
2020-09-01 13:16:50 +05:30
parent 218c9bcc18
commit 50d50e4ae9
5 changed files with 29 additions and 57 deletions

View File

@@ -71,16 +71,6 @@ describe('Test Connect', () => {
))
.finally (() => conn.close())
})
})
describe ('Reconnects', () => {
const verifyConnectionOpen = async (conn: WAConnection) => {
// check that the connection stays open
conn.on ('close', ({reason}) => (
reason !== DisconnectReason.intentional && assert.fail ('should not have closed again')
))
await delay (60*1000)
conn.close ()
}
it ('should disconnect & reconnect phone', async () => {
const conn = new WAConnection ()
await conn.loadAuthInfo('./auth_info.json').connect ()
@@ -103,6 +93,16 @@ describe ('Reconnects', () => {
conn.close ()
}
})
})
describe ('Reconnects', () => {
const verifyConnectionOpen = async (conn: WAConnection) => {
// check that the connection stays open
conn.on ('close', ({reason}) => (
reason !== DisconnectReason.intentional && assert.fail ('should not have closed again')
))
await delay (60*1000)
conn.close ()
}
/**
* the idea is to test closing the connection at multiple points in the connection
* and see if the library cleans up resources correctly
@@ -125,19 +125,13 @@ describe ('Reconnects', () => {
// exponentially increase the timeout disconnect
timeout *= 2
}
conn.on ('close', ({reason}) => (
// with v fast successive connections, WA sometimes incorrectly classifies a connection as taken over
(reason !== DisconnectReason.intentional && reason !== DisconnectReason.replaced) &&
assert.fail ('should not have closed again')
))
await delay (90*1000)
conn.close ()
await verifyConnectionOpen (conn)
})
/**
* the idea is to test closing the connection at multiple points in the connection
* and see if the library cleans up resources correctly
*/
it('should cleanup correctly 2', async () => {
it('should disrupt connect loop', async () => {
const conn = new WAConnection()
conn.autoReconnect = ReconnectMode.onAllErrors
conn.connectOptions.timeoutMs = 20000
@@ -217,36 +211,6 @@ describe ('Reconnects', () => {
conn.close ()
}
})
it ('should disrupt connect loop', async () => {
const conn = new WAConnection ()
conn.loadAuthInfo ('./auth_info.json')
conn.connectOptions.maxRetries = 20
conn.connectOptions.timeoutMs = 20*1000
delay (3000)
.then (() => conn.close())
await assert.rejects( conn.connect () )
console.log ('rejected correctly')
delay (3000)
.then (() => conn['conn'].terminate())
.then (async () => {
while (conn['conn']) {
await delay(100)
}
console.log ('destroyed WS')
})
.then (() => delay(5000))
.then (() => conn['conn'].terminate())
await conn.connect ()
console.log ('opened connection')
await verifyConnectionOpen (conn)
})
it ('should reconnect & stay connected', async () => {
const conn = new WAConnection ()
conn.autoReconnect = ReconnectMode.onConnectionLost

View File

@@ -42,7 +42,8 @@ export class WAConnection extends EventEmitter {
connectOptions: WAConnectOptions = {
timeoutMs: 60*1000,
waitForChats: true,
maxRetries: 5
maxRetries: 5,
connectCooldownMs: 5000
}
/** When to auto-reconnect */
autoReconnect = ReconnectMode.onConnectionLost
@@ -70,7 +71,8 @@ export class WAConnection extends EventEmitter {
protected lastSeen: Date = null // last keep alive received
protected qrTimeout: NodeJS.Timeout
protected lastDisconnectReason: DisconnectReason
protected lastConnectTime: Date = null
protected lastDisconnectReason: DisconnectReason
constructor () {
super ()
@@ -311,7 +313,6 @@ export class WAConnection extends EventEmitter {
this.msgCount = 0
this.phoneConnected = false
this.lastDisconnectReason = reason
this.endConnection ()
@@ -319,14 +320,14 @@ export class WAConnection extends EventEmitter {
this.pendingRequests.forEach (({reject}) => reject(new Error('close')))
this.pendingRequests = []
}
// reconnecting if the timeout is active for the reconnect loop
this.emit ('close', { reason, isReconnecting })
}
protected endConnection () {
this.conn?.removeAllListeners ('close')
this.conn?.close()
this.conn?.removeAllListeners ('message')
this.conn?.close ()
this.conn?.terminate()
this.conn = null
this.lastSeen = null

View File

@@ -18,8 +18,11 @@ export class WAConnection extends Base {
while (this.state === 'connecting') {
tries += 1
try {
// if the first try failed, delay & connect again
await this.connectInternal (options, tries > 1 && 2000)
const diff = this.lastConnectTime ? new Date().getTime()-this.lastConnectTime.getTime() : Infinity
await this.connectInternal (
options,
diff > this.connectOptions.connectCooldownMs ? 0 : this.connectOptions.connectCooldownMs
)
this.phoneConnected = true
this.state = 'open'
@@ -34,6 +37,8 @@ export class WAConnection extends Base {
}
if (!willReconnect) throw error
} finally {
this.lastConnectTime = new Date()
}
}

View File

@@ -65,6 +65,8 @@ export type WAConnectOptions = {
maxRetries?: number
/** should the chats be waited for */
waitForChats?: boolean
connectCooldownMs?: number
}
export type WAConnectionState = 'open' | 'connecting' | 'close'

View File

@@ -123,7 +123,7 @@ export const openWebSocketConnection = (timeoutMs: number, retryOnNetworkError:
try {
const ws = await newWS()
if (cancelled) {
ws.close ()
ws.terminate ()
break
} else return ws
} catch (error) {