Sourcegraph DocsSourcegraph Docs
  • Code Intelligence

    • Cody
    • Code Search
  • Code Management

    • Batch Changes
    • Code Navigation
    • Code Monitoring
    • Code Ownership
    • Code Insights
    • Notebooks
  • Platform

    • Sourcegraph Admin
    • Sourcegraph Cloud
    • Integrations
    • Development
  • CLI & API

    • Sourcegraph CLI
    • Sourcegraph GraphQL API
    • Sourcegraph Stream API
  • Help & Support

    • SLAs & Premium Support
    • Tutorials
    • Sourcegraph Accounts
    • Changelog
  1. Docs
  2. dev
  3. background-information
  4. backgroundroutine

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 a goroutine.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

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)

On this page

  1. Developing a background routine

    1. Adding a background routine
    1. Adding a periodic background routine