timer.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package logic
  2. import (
  3. "context"
  4. "fmt"
  5. "sync"
  6. "time"
  7. "github.com/gravitl/netmaker/logger"
  8. "github.com/gravitl/netmaker/servercfg"
  9. "golang.org/x/exp/slog"
  10. "github.com/gravitl/netmaker/models"
  11. )
  12. // == Constants ==
  13. // How long to wait before sending telemetry to server (24 hours)
  14. const timer_hours_between_runs = 24
  15. // HookManagerCh - channel to add any new hooks
  16. var HookManagerCh = make(chan models.HookDetails, 3)
  17. // == Public ==
  18. // TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
  19. func TimerCheckpoint() error {
  20. // get the telemetry record in the DB, which contains a timestamp
  21. telRecord, err := fetchTelemetryRecord()
  22. if err != nil {
  23. return err
  24. }
  25. sendtime := time.Unix(telRecord.LastSend, 0).Add(time.Hour * time.Duration(timer_hours_between_runs))
  26. // can set to 2 minutes for testing
  27. // sendtime := time.Unix(telRecord.LastSend, 0).Add(time.Minute * 2)
  28. enoughTimeElapsed := time.Now().After(sendtime)
  29. // if more than 24 hours has elapsed, send telemetry to posthog
  30. if enoughTimeElapsed {
  31. // run any time hooks
  32. runHooks()
  33. return setTelemetryTimestamp(&telRecord)
  34. }
  35. return nil
  36. }
  37. // AddHook - adds a hook function to run every 24hrs
  38. func AddHook(ifaceToAdd interface{}) {
  39. timeHooks = append(timeHooks, ifaceToAdd)
  40. }
  41. // StartHookManager - listens on `HookManagerCh` to run any hook
  42. func StartHookManager(ctx context.Context, wg *sync.WaitGroup) {
  43. defer wg.Done()
  44. for {
  45. select {
  46. case <-ctx.Done():
  47. slog.Error("## Stopping Hook Manager")
  48. return
  49. case newhook := <-HookManagerCh:
  50. addHook := true
  51. if servercfg.IsDeloyedOnK8s() && !K8sMasterPod() {
  52. addHook = false
  53. }
  54. if addHook {
  55. wg.Add(1)
  56. go addHookWithInterval(ctx, wg, newhook.Hook, newhook.Interval)
  57. }
  58. }
  59. }
  60. }
  61. func addHookWithInterval(ctx context.Context, wg *sync.WaitGroup, hook func() error, interval time.Duration) {
  62. defer wg.Done()
  63. ticker := time.NewTicker(interval)
  64. defer ticker.Stop()
  65. for {
  66. select {
  67. case <-ctx.Done():
  68. return
  69. case <-ticker.C:
  70. if err := hook(); err != nil {
  71. slog.Error(err.Error())
  72. }
  73. }
  74. }
  75. }
  76. // == private ==
  77. // timeHooks - functions to run once a day, functions must take no parameters
  78. var timeHooks = []interface{}{
  79. loggerDump,
  80. sendTelemetry,
  81. }
  82. func loggerDump() error {
  83. // TODO use slog?
  84. logger.DumpFile(fmt.Sprintf("data/netmaker.log.%s", time.Now().Format(logger.TimeFormatDay)))
  85. return nil
  86. }
  87. // runHooks - runs the functions currently in the timeHooks data structure
  88. func runHooks() {
  89. for _, hook := range timeHooks {
  90. if err := hook.(func() error)(); err != nil {
  91. slog.Error("error occurred when running timer function", "error", err.Error())
  92. }
  93. }
  94. }