github.com/nais/knorten@v0.0.0-20240104110906-55926958e361/pkg/leaderelection/leaderelection.go (about) 1 package leaderelection 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "os" 9 "time" 10 ) 11 12 func IsLeader() (bool, error) { 13 electorPath := os.Getenv("ELECTOR_PATH") 14 if electorPath == "" { 15 // local development 16 return true, nil 17 } 18 19 hostname, err := os.Hostname() 20 if err != nil { 21 return false, err 22 } 23 24 leader, err := getLeader(electorPath) 25 if err != nil { 26 return false, err 27 } 28 29 return hostname == leader, nil 30 } 31 32 func getLeader(electorPath string) (string, error) { 33 resp, err := electorRequestWithRetry(electorPath, 3) 34 if err != nil { 35 return "", err 36 } 37 defer resp.Body.Close() 38 bodyBytes, err := io.ReadAll(resp.Body) 39 if err != nil { 40 return "", err 41 } 42 43 var electorResponse struct { 44 Name string 45 } 46 47 if err := json.Unmarshal(bodyBytes, &electorResponse); err != nil { 48 return "", err 49 } 50 51 return electorResponse.Name, nil 52 } 53 54 func electorRequestWithRetry(electorPath string, numRetries int) (*http.Response, error) { 55 for i := 1; i <= numRetries; i++ { 56 resp, err := http.Get("http://" + electorPath) 57 if err == nil { 58 return resp, nil 59 } 60 time.Sleep(time.Second * time.Duration(i)) 61 } 62 63 return nil, fmt.Errorf("no response from elector container after %v retries", numRetries) 64 }