blob: 6980042b606a39cf8b5235240b2c373a2392c05d [file] [log] [blame]
Philipp Schradera9a79392023-03-25 13:28:31 -07001package background_task
Philipp Schraderc49eaf72023-02-26 16:56:52 -08002
3import (
4 "time"
5)
6
Philipp Schrader3f0e36f2023-03-25 13:49:41 -07007// A helper to run a function in the background at a specified interval.
8// Can be used for a lot of different things.
9type backgroundTask struct {
Philipp Schraderb15f4bd2023-03-25 14:21:38 -070010 ticker *time.Ticker
11 stopRequested chan bool
12 done chan bool
Philipp Schraderc49eaf72023-02-26 16:56:52 -080013}
14
Philipp Schrader3f0e36f2023-03-25 13:49:41 -070015func New(interval time.Duration) backgroundTask {
16 return backgroundTask{
Philipp Schraderb15f4bd2023-03-25 14:21:38 -070017 ticker: time.NewTicker(interval),
18 stopRequested: make(chan bool, 1),
19 done: make(chan bool, 1),
Philipp Schrader3f0e36f2023-03-25 13:49:41 -070020 }
21}
Philipp Schraderc49eaf72023-02-26 16:56:52 -080022
Philipp Schrader3f0e36f2023-03-25 13:49:41 -070023func (task *backgroundTask) Start(taskFunc func()) {
Philipp Schraderc49eaf72023-02-26 16:56:52 -080024 go func() {
Philipp Schraderb15f4bd2023-03-25 14:21:38 -070025 // Signal the Stop() function below when the goroutine has
26 // finished executing.
27 defer func() { task.done <- true }()
28
29 // time.Ticker doesn't perform an immediate invocation.
30 // Instead, it waits for the specified duration before
31 // triggering the first tick. We pretend that there's a tick
32 // here by invoking the callback manually.
33 taskFunc()
34
Philipp Schraderc49eaf72023-02-26 16:56:52 -080035 for {
Philipp Schraderb15f4bd2023-03-25 14:21:38 -070036 select {
37 case <-task.stopRequested:
38 return
39 case <-task.ticker.C:
Philipp Schrader3f0e36f2023-03-25 13:49:41 -070040 taskFunc()
Philipp Schraderc49eaf72023-02-26 16:56:52 -080041 }
Philipp Schraderc49eaf72023-02-26 16:56:52 -080042 }
Philipp Schraderc49eaf72023-02-26 16:56:52 -080043 }()
44}
45
Philipp Schrader3f0e36f2023-03-25 13:49:41 -070046func (task *backgroundTask) Stop() {
Philipp Schraderb15f4bd2023-03-25 14:21:38 -070047 task.stopRequested <- true
48 task.ticker.Stop()
49 <-task.done
50 close(task.stopRequested)
51 close(task.done)
Philipp Schraderc49eaf72023-02-26 16:56:52 -080052}