utils.go 1.9 KB

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