Last active
February 1, 2021 17:39
-
-
Save hekmon/7c9c666e7267c0a1090395ee649ebdbf to your computer and use it in GitHub Desktop.
Golang "autostop" design pattern: controller with clean context stop (avoid Start() Stop() workflow)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package foobar | |
import ( | |
"context" | |
"errors" | |
) | |
// Controller is a base pattern controller | |
type Controller struct { | |
ctx context.Context | |
workers sync.WaitGroup | |
stopped chan struct{} | |
} | |
// New returns a initialized & started controller | |
func New(ctx context.Context) (c *Controller, err error) { | |
if ctx == nil { | |
err = errors.New("context can't be nill") | |
return | |
} | |
// Init | |
c = &Controller{ | |
ctx: ctx, | |
stopped: make(chan struct{}), | |
} | |
// Start workers | |
c.workers.Add(1) | |
go func() { | |
c.workerA() | |
c.workers.Done() | |
}() | |
c.workers.Add(1) | |
go func() { | |
c.workerB() | |
c.workers.Done() | |
}() | |
// Create the auto-stopper (must be launch after the worker(s) in case ctx is cancelled while launching workers) | |
go c.autostop() | |
// Return the initialized & started controller | |
return | |
} | |
func (c *Controller) autostop() { | |
// Wait for signal | |
<-c.ctx.Done() | |
// Begin the stopping proceedure | |
c.workers.Wait() | |
// TODO: save some state ? | |
// Close the stopped chan to indicate we are fully stopped | |
close(c.stopped) | |
} | |
// WaitStopped will block until c is fully stopped. | |
// To be stopped, c needs to have its context cancelled. | |
// WaitStopped is safe to be called from multiples goroutines. | |
func (c *Controller) WaitStopped() { | |
<-c.stopped | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment