-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.go
141 lines (117 loc) · 2.5 KB
/
main.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
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"sync"
"time"
)
var (
centralServerIP string
nodeId string
pingUrls []string
mu sync.Mutex
loopRunning bool
)
func init() {
centralServerIP = os.Getenv("CENTRAL_SERVER_IP")
if centralServerIP == "" {
fmt.Println("CENTRAL_SERVER_IP environment variable is required")
os.Exit(1)
}
}
func fetchPingUrls() error {
resp, err := http.Get(fmt.Sprintf("http://%s/register", centralServerIP))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to register and fetch ping URLs: %v", resp.Status)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
var response struct {
NodeId string `json:"nodeId"`
PingUrls []string `json:"pingUrls"`
}
err = json.Unmarshal(body, &response)
if err != nil {
return err
}
nodeId = response.NodeId
pingUrls = response.PingUrls
return nil
}
func ping(url string) (time.Duration, error) {
start := time.Now()
resp, err := http.Get(url)
if err != nil {
return 0, err
}
resp.Body.Close()
elapsed := fmt.Sprintf("%dms", time.Since(start).Milliseconds())
return elapsed, nil
}
func sendResults(results map[string]string) error {
url := fmt.Sprintf("http://%s/collect/%s", centralServerIP, nodeId)
data, err := json.Marshal(results)
if err != nil {
return err
}
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to send results: %v", resp.Status)
}
return nil
}
func runPingLoop() {
mu.Lock()
defer mu.Unlock()
if loopRunning {
fmt.Println("Previous loop still running, skipping this round.")
return
}
loopRunning = true
defer func() { loopRunning = false }()
results := make(map[string]string)
for _, url := range pingUrls {
elapsed, err := ping(url)
if err != nil {
fmt.Printf("Failed to ping %s: %v\n", url, err)
results[url] = "error"
continue
}
fmt.Printf("Ping to %s: %v\n", url, elapsed)
results[url] = elapsed.String()
}
err := sendResults(results)
if err != nil {
fmt.Printf("Failed to send results: %v\n", err)
}
}
func main() {
err := fetchPingUrls()
if err != nil {
fmt.Printf("Failed to fetch ping URLs: %v\n", err)
return
}
ticker := time.NewTicker(1 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
go runPingLoop()
}
}
}