/
heartbeat.go
82 lines (72 loc) · 1.66 KB
/
heartbeat.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
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package agent
import (
"sync"
"time"
)
const (
online = "online"
offline = "offline"
)
// svc keeps info on service live status.
// Services send heartbeat to nats thus updating last seen.
// When service doesnt send heartbeat for some time gets marked offline.
type svc struct {
info Info
interval time.Duration
ticker *time.Ticker
mu sync.Mutex
}
type Info struct {
Name string `json:"name"`
LastSeen time.Time `json:"last_seen"`
Status string `json:"status"`
Type string `json:"type"`
Terminal int `json:"terminal"`
}
// Heartbeat specifies api for updating status and keeping track on services
// that are sending heartbeat to NATS.
type Heartbeat interface {
Update()
Info() Info
}
// interval - duration of interval
// if service doesnt send heartbeat during interval it is marked offline.
func NewHeartbeat(name, svcType string, interval time.Duration) Heartbeat {
ticker := time.NewTicker(interval)
s := svc{
info: Info{
Name: name,
Status: online,
Type: svcType,
LastSeen: time.Now(),
},
ticker: ticker,
interval: interval,
}
s.listen()
return &s
}
func (s *svc) listen() {
go func() {
for range s.ticker.C {
// TODO - we can disable ticker when the status gets OFFLINE
// and on the next heartbeat enable it again.
s.mu.Lock()
if time.Now().After(s.info.LastSeen.Add(s.interval)) {
s.info.Status = offline
}
s.mu.Unlock()
}
}()
}
func (s *svc) Update() {
s.mu.Lock()
defer s.mu.Unlock()
s.info.LastSeen = time.Now()
s.info.Status = online
}
func (s *svc) Info() Info {
return s.info
}