GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

84 lines
1.5 KiB

  1. package task
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. )
  7. var globalCtx, globalCancel = context.WithCancel(context.Background())
  8. // A Task is a wrapper around a function that offers scheduling
  9. // and syncronization.
  10. type Task struct {
  11. mutex sync.Mutex
  12. ctx context.Context
  13. ctxCancel context.CancelFunc
  14. waitDuration time.Duration
  15. scheduled bool
  16. callback func() error
  17. }
  18. // Context gets the task's context.
  19. func (task *Task) Context() context.Context {
  20. return task.ctx
  21. }
  22. // Stop stops a task. This should not be done to stop a single run,
  23. // but as a way to cancel it forever.
  24. func (task *Task) Stop() {
  25. task.ctxCancel()
  26. }
  27. // Schedule schedules a task for later execution.
  28. func (task *Task) Schedule() {
  29. // Don't if the context is closed.
  30. select {
  31. case <-task.Context().Done():
  32. return
  33. default:
  34. }
  35. task.mutex.Lock()
  36. if task.scheduled {
  37. task.mutex.Unlock()
  38. return
  39. }
  40. task.scheduled = true
  41. task.mutex.Unlock()
  42. go func() {
  43. <-time.After(task.waitDuration)
  44. // Mark as no longer scheduled
  45. task.mutex.Lock()
  46. task.scheduled = false
  47. task.mutex.Unlock()
  48. // Don't if the task is cancelled
  49. select {
  50. case <-task.Context().Done():
  51. return
  52. default:
  53. }
  54. task.callback()
  55. }()
  56. }
  57. // New makes a new task with the callback.
  58. func New(waitDuration time.Duration, callback func() error) *Task {
  59. ctx, ctxCancel := context.WithCancel(globalCtx)
  60. return &Task{
  61. callback: callback,
  62. ctx: ctx,
  63. ctxCancel: ctxCancel,
  64. waitDuration: waitDuration,
  65. }
  66. }
  67. // StopAll stops all tasks.
  68. func StopAll() {
  69. globalCancel()
  70. }