-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheckup.go
171 lines (138 loc) · 3.39 KB
/
checkup.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package main
import (
"encoding/json"
"io/ioutil"
"log"
"os"
"sort"
"sync"
"time"
"github.com/pkg/errors"
"github.com/McKael/checkup"
)
var config checkup.Checkup
var index map[string]int64
var checkupFiles []string
var storageReader checkup.StorageReader
var lastUpdate struct {
timestamp time.Time
tsMutex, updateMutex sync.Mutex
}
func loadInitialData() error {
// Check we're using a supported storage backend
if sr, ok := config.Storage.(checkup.StorageReader); ok {
storageReader = sr
} else {
return errors.New("unsupported storage backend")
}
// Get index
idx, err := storageReader.GetIndex()
if err != nil {
return errors.Wrap(err, "cannot read index")
}
index = idx
chkFiles := make([]string, 0, len(index))
for i := range index {
chkFiles = append(chkFiles, i)
}
sort.Slice(chkFiles, func(i, j int) bool {
return index[chkFiles[i]] < index[chkFiles[j]]
})
checkupFiles = chkFiles
buildTimelines(checkupFiles)
return nil
}
func updateData() error {
//log.Print("Updating data") // DBG
lastUpdate.tsMutex.Lock()
if time.Since(lastUpdate.timestamp) < 20*time.Second {
//log.Print("NOT updating data") // DBG
lastUpdate.tsMutex.Unlock()
return nil
}
lastUpdate.timestamp = time.Now()
lastUpdate.tsMutex.Unlock()
lastUpdate.updateMutex.Lock()
defer lastUpdate.updateMutex.Unlock()
// Refresh index
indexNew, err := storageReader.GetIndex()
if err != nil {
return errors.Wrap(err, "cannot read index")
}
var newChkFiles []string
for i := range indexNew {
if _, ok := index[i]; !ok {
newChkFiles = append(newChkFiles, i)
index[i] = indexNew[i]
}
}
//log.Printf("Updating data: %d more records\n", len(newChkFiles)) // DBG
sort.Slice(newChkFiles, func(i, j int) bool {
return index[newChkFiles[i]] < index[newChkFiles[j]]
})
checkupFiles = append(checkupFiles, newChkFiles...)
sort.Slice(checkupFiles, func(i, j int) bool {
return index[checkupFiles[i]] < index[checkupFiles[j]]
})
buildTimelines(newChkFiles)
return nil
}
func loadCheckupConfiguration(configFile string) error {
configBytes, err := ioutil.ReadFile(configFile)
if err != nil {
errors.Wrap(err, "cannot read configuration file")
}
var c checkup.Checkup
err = json.Unmarshal(configBytes, &c)
if err != nil {
errors.Wrap(err, "cannot parse configuration file")
}
config = c
return nil
}
func getLatestCheck(t *time.Time) ([]checkup.Result, error) {
// TODO use cached data
l := len(checkupFiles)
if l == 0 {
return nil, nil
}
*t = time.Unix(0, index[checkupFiles[l-1]]).Local()
return storageReader.Fetch(checkupFiles[l-1])
}
func getSiteLatestCheck(site string) (checkup.Result, error) {
var checkRes checkup.Result
stl, err := GetTimeline(site, false, 0, 0, 1)
if err != nil {
return checkRes, err
}
l := len(stl)
if l == 0 {
return checkRes, nil
}
checkRes = *(stl[l-1].Result)
return checkRes, nil
}
func startUpdateTimer() {
ticker := time.NewTicker(5 * time.Minute)
go func() {
for range ticker.C {
if err := updateData(); err != nil {
log.Println("Error while updating: ", err)
}
}
}()
}
func initializeOutput() {
resetLogOutput()
disableColors()
}
// resetLogOutput reinitiaizes log output that is automatically
// disabled by checkup (!)
func resetLogOutput() {
log.SetOutput(os.Stderr)
}
// disableColors prevents checkup from using ANSI escape
// sequences in strings
func disableColors() {
checkup.DisableColor()
}