File: schedule.go

package info (click to toggle)
golang-github-atomicgo-schedule 0.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 120 kB
  • sloc: makefile: 2
file content (116 lines) | stat: -rw-r--r-- 2,565 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package schedule

import "time"

// Task holds information about the running task and can be used to stop running tasks.
type Task struct {
	stop          chan struct{}
	nextExecution time.Time
	startedAt     time.Time
}

// newTask creates a new Task.
func newTask() *Task {
	return &Task{
		stop:      make(chan struct{}),
		startedAt: time.Now(),
	}
}

// StartedAt returns the time when the scheduler was started.
func (s *Task) StartedAt() time.Time {
	return s.startedAt
}

// NextExecutionTime returns the time when the next execution will happen.
func (s *Task) NextExecutionTime() time.Time {
	return s.nextExecution
}

// ExecutesIn returns the duration until the next execution.
func (s *Task) ExecutesIn() time.Duration {
	return time.Until(s.nextExecution)
}

// IsActive returns true if the scheduler is active.
func (s *Task) IsActive() bool {
	select {
	case <-s.stop:
		return false
	default:
		return true
	}
}

// Wait blocks until the scheduler is stopped.
// After and At will stop automatically after the task is executed.
func (s *Task) Wait() {
	<-s.stop
}

// Stop stops the scheduler.
func (s *Task) Stop() {
	close(s.stop)
}

// After executes the task after the given duration.
// The function is non-blocking. If you want to wait for the task to be executed, use the Task.Wait method.
func After(d time.Duration, task func()) *Task {
	scheduler := newTask()
	scheduler.nextExecution = time.Now().Add(d)

	go func() {
		select {
		case <-time.After(d):
			task()
			scheduler.Stop()
		case <-scheduler.stop:
			return
		}
	}()

	return scheduler
}

// At executes the task at the given time.
// The function is non-blocking. If you want to wait for the task to be executed, use the Task.Wait method.
func At(t time.Time, task func()) *Task {
	scheduler := newTask()
	scheduler.nextExecution = t

	go func() {
		select {
		case <-time.After(time.Until(t)):
			task()
			scheduler.Stop()
		case <-scheduler.stop:
			return
		}
	}()

	return scheduler
}

// Every executes the task in the given interval, as long as the task function returns true.
// The function is non-blocking. If you want to wait for the task to be executed, use the Task.Wait method.
func Every(interval time.Duration, task func() bool) *Task {
	scheduler := newTask()
	scheduler.nextExecution = time.Now().Add(interval)

	ticker := time.NewTicker(interval)

	go func() {
		for {
			select {
			case <-ticker.C:
				task()
				scheduler.nextExecution = time.Now().Add(interval)
			case <-scheduler.stop:
				ticker.Stop()
				return
			}
		}
	}()

	return scheduler
}