<commit_before>package signalfx

import (
	"errors"
	"log"
	"time"
)

type BackgroundJob chan backgroundCommand

type backgroundCommand int

const (
	pauseCommand backgroundCommand = iota
	resumeCommand
	doCommand
)

var (
	// ErrBackgroundJobNotStarted indicates that a background job
	// has not been started (i.e., it's nil).
	ErrBackgroundJobNotStarted = errors.New("Background job not started")
)

func Background(interval time.Duration, doFunc func()) BackgroundJob {
	controlChan := make(BackgroundJob)
	go func() {
		paused := false
		ticker := time.NewTicker(interval)
		for {
			select {
			case <-ticker.C:
				doFunc()
			case command, ok := <-controlChan:
				if !ok {
					ticker.Stop()
					return
				}
				switch command {
				case pauseCommand:
					ticker.Stop()
					paused = true
				case resumeCommand:
					if paused {
						ticker = time.NewTicker(interval)
						paused = false
					}
				case doCommand:
					ticker.Stop()
					doFunc()
					ticker = time.NewTicker(interval)
				default:
					log.Printf("[ERR] background reporter: unknown command %d", command)
				}
			}
		}
	}()
	return controlChan
}

func (b BackgroundJob) Pause() error {
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- pauseCommand
	return nil
}

func (b BackgroundJob) Resume() error {
	// TODO: add better error checking, e.g. for started-but-not-paused
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- resumeCommand
	return nil
}

// Stop stops a background job.  It is an error to attempt to stop an
// already-stopped job.
func (b *BackgroundJob) Stop() error {
	if b == nil || *b == nil {
		return ErrBackgroundJobNotStarted
	}
	close(*b)
	*b = nil
	return nil
}

func (b BackgroundJob) Do() error {
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- doCommand
	return nil
}<commit_msg>Fill out documentation<commit_after>package signalfx

import (
	"errors"
	"log"
	"time"
)

// A BackgroundJob represents a goroutine which will periodically
// call a function every time interval.
type BackgroundJob chan backgroundCommand

type backgroundCommand int

const (
	pauseCommand backgroundCommand = iota
	resumeCommand
	doCommand
)

var (
	// ErrBackgroundJobNotStarted indicates that a background job
	// has not been started (i.e., it's nil).
	ErrBackgroundJobNotStarted = errors.New("Background job not started")
)

// Background spawns a background goroutine which will call the
// passed-in function every time interval.
func Background(interval time.Duration, doFunc func()) BackgroundJob {
	controlChan := make(BackgroundJob)
	go func() {
		paused := false
		ticker := time.NewTicker(interval)
		for {
			select {
			case <-ticker.C:
				doFunc()
			case command, ok := <-controlChan:
				if !ok {
					ticker.Stop()
					return
				}
				switch command {
				case pauseCommand:
					ticker.Stop()
					paused = true
				case resumeCommand:
					if paused {
						ticker = time.NewTicker(interval)
						paused = false
					}
				case doCommand:
					ticker.Stop()
					doFunc()
					ticker = time.NewTicker(interval)
				default:
					log.Printf("[ERR] background reporter: unknown command %d", command)
				}
			}
		}
	}()
	return controlChan
}

// Pause pauses the clock (it does not pause a running job).  It is
// not an error to call Pause on a paused job.
func (b BackgroundJob) Pause() error {
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- pauseCommand
	return nil
}

// Resume resumes a paused job.  It is not an error to call Resume on
// a running job.
func (b BackgroundJob) Resume() error {
	// TODO: add better error checking, e.g. for started-but-not-paused
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- resumeCommand
	return nil
}

// Stop stops a background job.  It is an error to attempt to stop an
// already-stopped job.
func (b *BackgroundJob) Stop() error {
	if b == nil || *b == nil {
		return ErrBackgroundJobNotStarted
	}
	close(*b)
	*b = nil
	return nil
}

// Do runs the job immediately, then resumes the normal
// wait-then-execute pattern.
func (b BackgroundJob) Do() error {
	if b == nil {
		return ErrBackgroundJobNotStarted
	}
	b <- doCommand
	return nil
}
{'fraction_non_alphanumeric': 0.098821832171195, 'fraction_numerical': 0.0, 'mean_word_length': 3.118811881188119, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7077532', 'n_tokens_mistral': 1533, 'n_tokens_neox': 1322, 'n_words': 439}