utils.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package utils
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "net"
  6. "runtime"
  7. "strings"
  8. "time"
  9. )
  10. // RetryStrategy specifies a strategy to retry an operation after waiting a while,
  11. // with hooks for successful and unsuccessful (>=max) tries.
  12. type RetryStrategy struct {
  13. Wait func(time.Duration)
  14. WaitTime time.Duration
  15. WaitTimeIncrease time.Duration
  16. MaxTries int
  17. Try func() error
  18. OnMaxTries func()
  19. OnSuccess func()
  20. }
  21. // DoStrategy does the retry strategy specified in the struct, waiting before retrying an operator,
  22. // up to a max number of tries, and if executes a success "finalizer" operation if a retry is successful
  23. func (rs RetryStrategy) DoStrategy() {
  24. err := rs.Try()
  25. if err == nil {
  26. rs.OnSuccess()
  27. return
  28. }
  29. tries := 1
  30. for {
  31. if tries >= rs.MaxTries {
  32. rs.OnMaxTries()
  33. return
  34. }
  35. rs.Wait(rs.WaitTime)
  36. if err := rs.Try(); err != nil {
  37. tries++ // we tried, increase count
  38. rs.WaitTime += rs.WaitTimeIncrease // for the next time, sleep more
  39. continue // retry
  40. }
  41. rs.OnSuccess()
  42. return
  43. }
  44. }
  45. func TraceCaller() {
  46. // Skip 1 frame to get the caller of this function
  47. pc, file, line, ok := runtime.Caller(2)
  48. if !ok {
  49. slog.Debug("Unable to get caller information")
  50. return
  51. }
  52. // Get function name from the program counter (pc)
  53. funcName := runtime.FuncForPC(pc).Name()
  54. // Print trace details
  55. slog.Debug("Called from function: %s\n", "func-name", funcName)
  56. slog.Debug("File: %s, Line: %d\n", "file", file, "line-no", line)
  57. }
  58. // NoEmptyStringToCsv takes a bunch of strings, filters out empty ones and returns a csv version of the string
  59. func NoEmptyStringToCsv(strs ...string) string {
  60. var sb strings.Builder
  61. for _, str := range strs {
  62. trimmedStr := strings.TrimSpace(str)
  63. if trimmedStr != "" && trimmedStr != "<nil>" {
  64. if sb.Len() > 0 {
  65. sb.WriteString(", ")
  66. }
  67. sb.WriteString(str)
  68. }
  69. }
  70. return sb.String()
  71. }
  72. // GetExtClientEndpoint returns the external client endpoint in the format "host:port" or "[host]:port" for IPv6
  73. func GetExtClientEndpoint(hostIpv4Endpoint, hostIpv6Endpoint net.IP, hostListenPort int) string {
  74. if hostIpv4Endpoint.To4() == nil {
  75. return fmt.Sprintf("[%s]:%d", hostIpv6Endpoint.String(), hostListenPort)
  76. } else {
  77. return fmt.Sprintf("%s:%d", hostIpv4Endpoint.String(), hostListenPort)
  78. }
  79. }