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.newSpecExpireWorker
returns agoroutine.PeriodicGoroutine
, which means it's invoked periodically.- out-of-band migrations are implemented as background routines.
HardDeleter
is 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
goroutine.BackgroundRoutine
interface
Step 1: Implement the 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)