Routine orchestrator for your application
Find a file
Alexander Kiryukhin c86dd5f3d7
Fixed:
- ListenOsSignal handler now not in waitgroup. Before if all routines exited by itself (with DoNothingIfDone or DoNothingIfFail policies) waitgroup waits OS listener to complete
2019-04-04 10:15:18 +03:00
example Added: 2019-04-03 23:55:11 +03:00
.gitignore Initial commit 2018-12-05 00:48:33 +03:00
go.mod Update go.mod 2019-04-03 23:56:00 +03:00
go.sum Many changes 2019-01-17 07:54:39 +03:00
LICENSE Initial commit 2018-12-05 00:48:33 +03:00
mixins.go Added: 2019-04-03 23:55:11 +03:00
options.go Flexible run policies 2019-03-27 02:44:38 +03:00
README.md Added: 2019-04-03 23:55:11 +03:00
rutina.go Fixed: 2019-04-04 10:15:18 +03:00
rutina_test.go Flexible run policies 2019-03-27 02:44:38 +03:00

rutina

Package Rutina (russian "рутина" - ordinary boring everyday work) is routine orchestrator for your application.

It seems like https://godoc.org/golang.org/x/sync/errgroup with some different:

  1. propagates context to every routines. So routine can check if context stopped (ctx.Done()).
  2. has flexible run/stop policy. i.e. one routine restarts when it fails (useful on daemons) but if fails another - all routines will be cancelled
  3. already has optional signal handler ListenOsSignals()

When it need?

Usually, when your program consists of several routines (i.e.: http server, metrics server and os signals subscriber) and you want to stop all routines when one of them ends (i.e.: by TERM os signal in signal subscriber).

Usage

New instance

r := rutina.New()

or with optional mixins (see below):

r := rutina.New(...Mixins)

or

r.With(...Mixins)

Start new routine

r.Go(func (ctx context.Context) error {
    ...do something...
}, ...runOptions)

Available options of run policy:

  • ShutdownIfFail - Shutdown all routines if this routine fails
  • RestartIfFail - Restart this routine if it fail
  • DoNothingIfFail - Do nothing just stop this routine if it fail
  • ShutdownIfDone - Shutdown all routines if this routine done without errors
  • RestartIfDone - Restart if this routine done without errors
  • DoNothingIfDone - Do nothing if this routine done without errors

Default policy:

ShutdownIfFail && ShutdownIfDone

(just like errgroup)

Example of run policies

r.Go(func(ctx context.Context) error {
	// If this routine produce no error - it just restarts
	// If it returns error - all other routines will shutdown (because context cancels)
}, rutina.RestartIfDone, rutina.ShutdownIfFail)

r.Go(func(ctx context.Context) error {
	// If this routine produce no error - it just completes
	// If it returns error - all other routines will shutdown (because context cancels)
}, rutina.DoNothingIfDone, rutina.ShutdownIfFail)

r.Go(func(ctx context.Context) error {
	// If this routine produce no error - all other routines will shutdown (because context cancels)
	// If it returns error - it will be restarted
}, rutina.RestartIfFail)

r.Go(func(ctx context.Context) error {
	// If this routine stopped by any case - all other routines will shutdown (because context cancels)
}, rutina.ShutdownIfDone)

r.ListenOsSignals() // Shutdown all routines by OS signal

Wait routines to complete

err := r.Wait()

Here err = error that shutdowns all routines (may be will be changed at future)

Mixins

Usage

r := rutina.New(mixin1, mixin2, ...)

or

r := rutina.New()
r = r.With(mixin1, mixin2, ...) // Returns new instance of Rutina!

Logger

r = r.With(rutina.WithStdLogger())

or

r = r.With(rutina.WithLogger(logger log.Logger))

Sets standard or custom logger. By default there is no logger.

Custom context

r = r.With(rutina.WithContext(ctx context.Context))

Propagates your own context to Rutina. By default it use own context.

Errors channel

errChan := make(chan error)
r = r.With(rutina.WithErrChan(errChan))

This channel will receive all errors from all routines with any ...Fail run policy.

Example

HTTP server with graceful shutdown example/http_server.go

Different run policies example/policies.go