-
Notifications
You must be signed in to change notification settings - Fork 15
/
ping.go
82 lines (70 loc) · 1.83 KB
/
ping.go
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
package reign
import (
"encoding/gob"
"net"
"time"
"github.com/thejerf/reign/internal"
)
var (
// DefaultPingInterval determines the minimum interval between PING messages.
DefaultPingInterval = time.Second * 30
// MaxSequentialPingFailures is the maximum number of sequential ping failures
// tolerable before the pinger panics, triggering a service restart if running
// under suture.
MaxSequentialPingFailures uint8 = 5
)
// pingRemote sends a "ping" message to the output encoder on an interval read off the
// resetTimer channel. This interval is used until one greater than 0 is put on the
// channel.
//
// An initial interval can be put on the resetTimer channel before calling this function.
// Otherwise, the DefaultPingInterval is used.
//
// This function is meant to run as a goroutine. The function will exit when the
// resetTimer channel is closed.
func pingRemote(output *gob.Encoder, resetTimer <-chan time.Duration, log ClusterLogger) {
var (
failureCount uint8
interval = DefaultPingInterval
ping internal.ClusterMessage = internal.Ping{}
)
// Set the interval if there's already one on the channel. Otherwise,
// use the default.
select {
case i := <-resetTimer:
if i > 0 {
interval = i
}
default:
}
t := time.NewTimer(interval)
for {
select {
case i, ok := <-resetTimer:
if !ok {
return
}
if i > 0 {
interval = i
}
// Stop the current timer and drain its channel if necessary.
if !t.Stop() {
<-t.C
}
_ = t.Reset(interval)
case <-t.C:
err := output.Encode(&ping)
if err != nil {
failureCount++
netErr, ok := err.(net.Error)
if !ok || !netErr.Temporary() || failureCount >= MaxSequentialPingFailures {
panic(err)
}
log.Error(err)
} else {
failureCount = 0
}
_ = t.Reset(interval)
}
}
}