timer.go 2.5 KB

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