I have a goroutine “process things”; from another goroutine, I want to send signal “resume processing things”, which means “if things are already processing, do nothing; otherwise, spawn processor”.
My current code works, but I wonder if there is a simpler pattern.
// this runs forever, resuming processing when signalled into
// the "this.resume" channel. Bursts of resume calls need to be supported
func (this *jobQueue) feedJobQueue() {
stopped := make(chan struct{})
running := false
for {
select {
case <-this.resume:
if running {
continue;
}
running = true
// process things!
go func() {
for {
job := this.pullNextJob()
if job == nil {
stopped <- struct{}{}
return
}
this.jobs <- *job
}
}()
case <-stopped:
running = false
}
}
}
“things to process” are added in bursts from multiple goroutines, and added to persistent store; each time new job is queued, notification is sent to this.resume
; the processing itself, however, takes a long time; this.jobs
queue is consumed slowly one by one.
I know this sounds a lot like persistent MQ queues, but there are many reasons why I don’t want to use that for this particular context.