forked from meteor/meteor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheartbeat.js
100 lines (88 loc) · 2.97 KB
/
heartbeat.js
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
96
97
98
99
100
// Heartbeat options:
// heartbeatInterval: interval to send pings, in milliseconds.
// heartbeatTimeout: timeout to close the connection if a reply isn't
// received, in milliseconds.
// sendPing: function to call to send a ping on the connection.
// onTimeout: function to call to close the connection.
DDPCommon.Heartbeat = function (options) {
var self = this;
self.heartbeatInterval = options.heartbeatInterval;
self.heartbeatTimeout = options.heartbeatTimeout;
self._sendPing = options.sendPing;
self._onTimeout = options.onTimeout;
self._seenPacket = false;
self._heartbeatIntervalHandle = null;
self._heartbeatTimeoutHandle = null;
};
_.extend(DDPCommon.Heartbeat.prototype, {
stop: function () {
var self = this;
self._clearHeartbeatIntervalTimer();
self._clearHeartbeatTimeoutTimer();
},
start: function () {
var self = this;
self.stop();
self._startHeartbeatIntervalTimer();
},
_startHeartbeatIntervalTimer: function () {
var self = this;
self._heartbeatIntervalHandle = Meteor.setInterval(
_.bind(self._heartbeatIntervalFired, self),
self.heartbeatInterval
);
},
_startHeartbeatTimeoutTimer: function () {
var self = this;
self._heartbeatTimeoutHandle = Meteor.setTimeout(
_.bind(self._heartbeatTimeoutFired, self),
self.heartbeatTimeout
);
},
_clearHeartbeatIntervalTimer: function () {
var self = this;
if (self._heartbeatIntervalHandle) {
Meteor.clearInterval(self._heartbeatIntervalHandle);
self._heartbeatIntervalHandle = null;
}
},
_clearHeartbeatTimeoutTimer: function () {
var self = this;
if (self._heartbeatTimeoutHandle) {
Meteor.clearTimeout(self._heartbeatTimeoutHandle);
self._heartbeatTimeoutHandle = null;
}
},
// The heartbeat interval timer is fired when we should send a ping.
_heartbeatIntervalFired: function () {
var self = this;
// don't send ping if we've seen a packet since we last checked,
// *or* if we have already sent a ping and are awaiting a timeout.
// That shouldn't happen, but it's possible if
// `self.heartbeatInterval` is smaller than
// `self.heartbeatTimeout`.
if (! self._seenPacket && ! self._heartbeatTimeoutHandle) {
self._sendPing();
// Set up timeout, in case a pong doesn't arrive in time.
self._startHeartbeatTimeoutTimer();
}
self._seenPacket = false;
},
// The heartbeat timeout timer is fired when we sent a ping, but we
// timed out waiting for the pong.
_heartbeatTimeoutFired: function () {
var self = this;
self._heartbeatTimeoutHandle = null;
self._onTimeout();
},
messageReceived: function () {
var self = this;
// Tell periodic checkin that we have seen a packet, and thus it
// does not need to send a ping this cycle.
self._seenPacket = true;
// If we were waiting for a pong, we got it.
if (self._heartbeatTimeoutHandle) {
self._clearHeartbeatTimeoutTimer();
}
}
});