Developing a background routine
Background routines are long running processes in our backend binaries.
They are defined in the goroutine package.
Examples:
worker.NewWorker, for example, produces a background routine, which in this case is a background worker.batches.newSpecExpireWorkerreturns agoroutine.PeriodicGoroutine, which means it's invoked periodically.- out-of-band migrations are implemented as background routines.
HardDeleteris a periodic background routine that periodically hard-deletes soft-deleted upload records.
See also the godocs.io examples for the goroutine package.
Adding a background routine
Step 1: Implement the goroutine.BackgroundRoutine interface
In order to be managed by the utilities in the goroutine package, a background routine needs to implement the goroutine.BackgroundRoutine interface.
type myRoutine struct {
done chan struct{}
}
func (m *myRoutine) Start() {
for {
select {
case <-m.done:
fmt.Println("done!")
return
default:
}
fmt.Println("Hello there!")
time.Sleep(1 * time.Second)
}
}
func (m *myRoutine) Stop() {
m.done <- struct{}{}
}Step 2: Start and monitor the background routine
With myRoutine defined, we can start and monitor it in a separate goroutine:
func main() {
r := &myRoutine{
done: make(chan struct{}),
}
ctx, cancel := context.WithCancel(context.Background())
// Make sure to run this in a separate goroutine
go goroutine.MonitorBackgroundRoutines(ctx, r)
// Give the background routine some time to do its work...
time.Sleep(2 * time.Second)
// ... and then cancel the context.
cancel()
// The routine will stop now, but let's give it some time to print its
// message
time.Sleep(1 * time.Second)
}Canceling the ctx will signal to MonitorBackgroundRoutines that it should Stop() the background routines.
If we run this we'll see the following output:
Hello there!
Hello there!
done!Adding a periodic background routine
Step 1: Define a handler
Use the goroutine.NewHandlerWithErrorMessage helper to create a handler function that implements the goroutine.HandlerFunc interface:
myHandler := goroutine.NewHandlerWithErrorMessage("this is my cool handler", func(ctx context.Context) error {
fmt.Println("Hello from the background!")
// Talk to the database, send HTTP requests, etc.
return nil
})Step 2: Create periodic goroutine from handler
With myHandler defined, we can create a periodic goroutine using goroutine.NewPeriodicGoroutine:
myPeriodicGoroutine := goroutine.NewPeriodicGoroutine(ctx, 2*time.Minute, myHandler)Step 3: Start and monitor the background routine
The last step is to start the routine in a goroutine and monitor it:
go goroutine.MonitorBackgroundRoutines(ctx, myPeriodicGoroutine)