-
Notifications
You must be signed in to change notification settings - Fork 385
/
Copy pathheartbeat.ts
95 lines (84 loc) · 2.38 KB
/
heartbeat.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { Package } from 'pinus-protocol';
import { getLogger } from 'pinus-logger';
import { ISocket } from '../../interfaces/ISocket';
let logger = getLogger('pinus', __filename);
export interface HeartbeatCommandOptions
{
disconnectOnTimeout?: boolean;
heartbeat?: number;
timeout?: number;
}
/**
* Process heartbeat request.
*
* @param {Object} opts option request
* opts.heartbeat heartbeat interval
*/
export class HeartbeatCommand
{
heartbeat: number;
timeout: number;
disconnectOnTimeout: boolean;
timeouts: { [socketId: number]: NodeJS.Timer } = {};
clients: { [socketId: number]: number } = {};
constructor(opts?: HeartbeatCommandOptions)
{
opts = opts || {};
this.disconnectOnTimeout = opts.disconnectOnTimeout;
if (opts.heartbeat)
{
this.heartbeat = opts.heartbeat * 1000; // heartbeat interval
this.timeout = opts.timeout * 1000 || this.heartbeat * 2; // max heartbeat message timeout
this.disconnectOnTimeout = true;
}
};
handle(socket: ISocket)
{
if (!this.heartbeat)
{
// no heartbeat setting
return;
}
let self = this;
if (!this.clients[socket.id])
{
// clear timers when socket disconnect or error
this.clients[socket.id] = 1;
socket.once('disconnect', this.clearTimers.bind(this, socket.id));
socket.once('error', this.clearTimers.bind(this, socket.id));
}
// clear timeout timer
if (self.disconnectOnTimeout)
{
this.clear(socket.id);
}
socket.sendRaw(Package.encode(Package.TYPE_HEARTBEAT));
if (self.disconnectOnTimeout)
{
self.timeouts[socket.id] = setTimeout(function ()
{
logger.info('client %j heartbeat timeout.', socket.id);
socket.disconnect();
}, self.timeout);
}
};
clear(id: number)
{
let tid = this.timeouts[id];
if (tid)
{
clearTimeout(tid);
delete this.timeouts[id];
}
};
clearTimers(id: number)
{
delete this.clients[id];
let tid = this.timeouts[id];
if (tid)
{
clearTimeout(tid);
delete this.timeouts[id];
}
}
}