/
health.go
83 lines (71 loc) · 2.02 KB
/
health.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
// Copyright 2023 the Paw Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package ui
import (
"bytes"
"fmt"
"log"
"net"
"os"
"time"
"lucor.dev/paw/internal/paw"
)
const (
timeout = 100 * time.Millisecond
)
// handleConnection handles the connection returning the paw version
func handleConnection(conn net.Conn) {
defer conn.Close()
// Send service information to the client and exits
_, err := conn.Write([]byte(paw.ServiceVersion() + "\n"))
if err != nil {
fmt.Println("Error writing server info:", err)
return
}
}
// HealthService starts a health service that listens on a random port.
// In the current implementation is used only to avoid starting multiple
// instances of the app.
func HealthService(lockFile string) (net.Listener, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
log.Println("could not start health service:", err)
return nil, err
}
defer listener.Close()
err = os.WriteFile(lockFile, []byte(listener.Addr().String()), 0644)
if err != nil {
log.Println("could not write health service lock file:", err)
return nil, err
}
for {
conn, err := listener.Accept()
if err != nil {
return listener, fmt.Errorf("health service: error accepting connection: %w", err)
}
go handleConnection(conn)
}
}
// HealthServiceCheck checks if the health service is running.
func HealthServiceCheck(lockFile string) bool {
address, err := os.ReadFile(lockFile)
if err != nil {
return false
}
conn, err := net.DialTimeout("tcp", string(address), timeout)
if err != nil {
return false
}
// Read the service version from the app and close the connection
conn.SetReadDeadline(time.Now().Add(timeout))
buffer := make([]byte, 4)
_, err = conn.Read(buffer)
conn.Close()
if err != nil {
return false
}
// check for paw service
return bytes.Equal([]byte(paw.ServicePrefix), buffer)
}