Skip to content

Commit 1a407f4

Browse files
committed
Properly handle heartbeat timeouts (#95)
On heartbeat timeout only the next RPC action was rejected, now `onerror` is called and the socket is closed. Fixes #95
1 parent d999538 commit 1a407f4

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

src/amqp-socket-client.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ export class AMQPClient extends AMQPBaseClient {
7878
socket.on('error', (err) => reject(new AMQPError(err.message, this)))
7979
const onConnect = (conn: AMQPBaseClient) => {
8080
socket.setTimeout(this.heartbeat * 1000) // reset timeout if heartbeats are disabled
81+
socket.on('timeout', () => {
82+
this.onerror(new AMQPError(`Heartbeat timeout`, this))
83+
this.closeSocket()
84+
})
8185
resolve(conn)
8286
}
8387
this.connectPromise = [onConnect, reject]

test/test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,3 +697,35 @@ test('should fail to connect to HTTP', async () => {
697697
const amqp = new AMQPClient("amqp://127.0.0.1:15672?heartbeat=1")
698698
await expect(amqp.connect()).rejects.toThrow()
699699
})
700+
701+
test('should handle heartbeat timeout correctly', async () => {
702+
const amqp = getNewClient({ heartbeat: 1 })
703+
const conn = await amqp.connect()
704+
705+
// Mock the socket timeout to simulate missed heartbeats
706+
const socket = amqp["socket"]
707+
assert(socket, "Socket must be created")
708+
709+
// Set up error callback to capture timeout error
710+
const errorPromise = new Promise<AMQPError>((resolve) => {
711+
conn.onerror = (err: AMQPError) => {
712+
resolve(err)
713+
}
714+
})
715+
716+
// Set up close promise to detect when socket is closed
717+
const closePromise = new Promise((resolve) => {
718+
socket.on('close', resolve)
719+
})
720+
721+
// Trigger timeout event to simulate heartbeat timeout
722+
socket.emit('timeout')
723+
724+
// Wait for error callback and socket close
725+
const error = await errorPromise
726+
await closePromise
727+
728+
// Verify error message and that connection is closed
729+
expect(error.message).toEqual('Heartbeat timeout')
730+
expect(conn.closed).toBe(true)
731+
})

0 commit comments

Comments
 (0)