mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-05 20:54:18 +08:00
88 lines
2.3 KiB
Go
88 lines
2.3 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"net"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// RetryStrategy specifies a strategy to retry an operation after waiting a while,
|
|
// with hooks for successful and unsuccessful (>=max) tries.
|
|
type RetryStrategy struct {
|
|
Wait func(time.Duration)
|
|
WaitTime time.Duration
|
|
WaitTimeIncrease time.Duration
|
|
MaxTries int
|
|
Try func() error
|
|
OnMaxTries func()
|
|
OnSuccess func()
|
|
}
|
|
|
|
// DoStrategy does the retry strategy specified in the struct, waiting before retrying an operator,
|
|
// up to a max number of tries, and if executes a success "finalizer" operation if a retry is successful
|
|
func (rs RetryStrategy) DoStrategy() {
|
|
err := rs.Try()
|
|
if err == nil {
|
|
rs.OnSuccess()
|
|
return
|
|
}
|
|
|
|
tries := 1
|
|
for {
|
|
if tries >= rs.MaxTries {
|
|
rs.OnMaxTries()
|
|
return
|
|
}
|
|
rs.Wait(rs.WaitTime)
|
|
if err := rs.Try(); err != nil {
|
|
tries++ // we tried, increase count
|
|
rs.WaitTime += rs.WaitTimeIncrease // for the next time, sleep more
|
|
continue // retry
|
|
}
|
|
rs.OnSuccess()
|
|
return
|
|
}
|
|
}
|
|
|
|
func TraceCaller() {
|
|
// Skip 1 frame to get the caller of this function
|
|
pc, file, line, ok := runtime.Caller(2)
|
|
if !ok {
|
|
slog.Debug("Unable to get caller information")
|
|
return
|
|
}
|
|
|
|
// Get function name from the program counter (pc)
|
|
funcName := runtime.FuncForPC(pc).Name()
|
|
|
|
// Print trace details
|
|
slog.Debug("Called from function: %s\n", "func-name", funcName)
|
|
slog.Debug("File: %s, Line: %d\n", "file", file, "line-no", line)
|
|
}
|
|
|
|
// NoEmptyStringToCsv takes a bunch of strings, filters out empty ones and returns a csv version of the string
|
|
func NoEmptyStringToCsv(strs ...string) string {
|
|
var sb strings.Builder
|
|
for _, str := range strs {
|
|
trimmedStr := strings.TrimSpace(str)
|
|
if trimmedStr != "" && trimmedStr != "<nil>" {
|
|
if sb.Len() > 0 {
|
|
sb.WriteString(", ")
|
|
}
|
|
sb.WriteString(str)
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
// GetExtClientEndpoint returns the external client endpoint in the format "host:port" or "[host]:port" for IPv6
|
|
func GetExtClientEndpoint(hostIpv4Endpoint, hostIpv6Endpoint net.IP, hostListenPort int) string {
|
|
if hostIpv4Endpoint.To4() == nil {
|
|
return fmt.Sprintf("[%s]:%d", hostIpv6Endpoint.String(), hostListenPort)
|
|
} else {
|
|
return fmt.Sprintf("%s:%d", hostIpv4Endpoint.String(), hostListenPort)
|
|
}
|
|
}
|