grace

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 14, 2021 License: MIT Imports: 9 Imported by: 2

README

Go Report Card PkgGoDev Test codecov GitHub License GitHub tag (latest by date)

grace

Easy graceful shutdowns in your go applications.

Table of Contents

Usage

First import the module:

go get github.com/tomwright/grace

Quickstart

package main

import (
    "context"
    "github.com/tomwright/grace"
    "time"
)

type myRunner struct {
}

func (mr *myRunner) Run(ctx context.Context) error {
    // Block until we are told to shutdown or until all work is done.
    <-ctx.Done()
    return nil
}

func main() {
    // Initialise grace.
    g := grace.Init(context.Background())

    // The following runners are equivalent.
    runnerA := &myRunner{}
    runnerB := grace.RunnerFunc(func(ctx context.Context) error {
        // Block until we are told to shutdown or until all work is done.
        <-ctx.Done()
        return nil
    })
	
    // Run both runners.
    g.Run(runnerA)
    g.Run(runnerB)

    go func() {
        // Manually shutdown after 2.5 seconds.
        // Alternatively leave this out and rely on os signals to shutdown.
        <-time.After(time.Millisecond * 2500)
        g.Shutdown()
    }()

    // Optionally wait for the shutdown signal to be sent.
    <-g.Context().Done()

    // Wait for all Runners to end.
    g.Wait()
}

Options

Grace allows you to modify the way it is initialised using InitOptions.

g := grace.Init(
  context.Background(),
  grace.InitOptionFn(func(g *grace.Grace) {
    g.LogFn = log.Printf
    g.ErrHandler = func(err error) bool {
    	g.LogFn("something terrible went wrong: %s", err.Error())
    	return true
    }
  })
)

Runners

Grace implements logic to execute and gracefully shutdown any number of Runners.

Each runner must react when the given contexts Done channel is closed.

A runner must implement the Runner interface. It can do this by implementing the Run(context.Context) error func, or by passing a func to RunnerFunc().

Pre-made Runners

Grace doesn't provide any runners in this module in order to reduce forced dependencies... instead please import the required modules below.

Implemented your own runner that you want to share? Raise a PR!

Triggering Shutdowns

Shutdowns can be triggered in a number of ways:

  1. SIGKILL will immediately terminate the application using os.Exit(1).
  2. SIGINT or SIGTERM will trigger a graceful shutdown. Sending 2 or more of these will immediately exit the application using os.Exit(1).
  3. Calling Shutdown() on a grace instance will start a graceful shutdown.
  4. Cancelling the context you gave to grace will start a graceful shutdown.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrShutdownSignalReceived is used when a shutdown signal is received.
	// It will cause a graceful shutdown.
	ErrShutdownSignalReceived = errors.New("shutdown signal received")

	// ErrShutdownRequestReceived is used when a shutdown is initiated without a signal.
	// It will cause a graceful shutdown.
	ErrShutdownRequestReceived = errors.New("shutdown request received")

	// ErrImmediateShutdownSignalReceived is used when a shutdown signal is received for the second time.
	// It will cause an immediate shutdown.
	ErrImmediateShutdownSignalReceived = errors.New("immediate shutdown signal received")
)

Functions

func DefaultErrorHandler

func DefaultErrorHandler(g *Grace) func(err error) bool

DefaultErrorHandler returns a standard error handler that will log errors and trigger a shutdown.

Types

type ErrHandlerFn

type ErrHandlerFn func(err error) bool

ErrHandlerFn is an error handler used to handle errors returned from Runners. Returns true if a graceful shutdown should be triggered as a result of the error.

type Grace

type Grace struct {
	// ErrHandler is the active error handler grace will pass errors to.
	ErrHandler ErrHandlerFn
	// LogFn is the log function that grace will use.
	LogFn func(format string, v ...interface{})
	// contains filtered or unexported fields
}

Grace manages Runners and handles errors.

func Init

func Init(ctx context.Context, options ...InitOption) *Grace

Init returns a new and initialised instance of Grace.

Example
package main

import (
	"context"
	"fmt"
	"github.com/tomwright/grace"
	"time"
)

func main() {
	g := grace.Init(context.Background())

	fmt.Println("Starting")

	g.Run(grace.RunnerFunc(func(ctx context.Context) error {
		for {
			select {
			case <-ctx.Done():
				fmt.Println("Graceful shutdown initiated")
				// Fake a 3 second shutdown
				for i := 3; i >= 0; i-- {
					fmt.Printf("Shutting down in %d\n", i)
					time.Sleep(time.Second * time.Duration(i))
				}
				return nil
			case <-time.After(time.Second):
				fmt.Println("Hello")
			}
		}
	}))

	go func() {
		<-time.After(time.Millisecond * 2500)
		fmt.Println("Triggering shutdown")
		g.Shutdown()
	}()

	fmt.Println("Started")
	<-g.Context().Done()

	g.Wait()
	fmt.Println("Shutdown")

}
Output:

Starting
Started
Hello
Hello
Triggering shutdown
Graceful shutdown initiated
Shutting down in 3
Shutting down in 2
Shutting down in 1
Shutting down in 0
Shutdown

func (*Grace) Context

func (l *Grace) Context() context.Context

Context returns the grace context. Use this throughout your application to be notified when a graceful shutdown has started.

func (*Grace) Run

func (l *Grace) Run(runner Runner)

Run runs a new Runner.

func (*Grace) Shutdown

func (l *Grace) Shutdown()

Shutdown will start a manual shutdown.

func (*Grace) Wait

func (l *Grace) Wait()

Wait will block until all Runners have stopped running.

type InitOption added in v0.1.2

type InitOption interface {
	// Apply allows you to apply options to the grace instance as it is being initialised.
	Apply(g *Grace)
}

InitOption allows you to modify the way grace is initialised.

func InitOptionFn added in v0.1.2

func InitOptionFn(fn func(g *Grace)) InitOption

InitOptionFn returns an InitOption that applies the given function.

type RecoveredPanicError added in v0.1.2

type RecoveredPanicError struct {
	// Err is the recovered error.
	Err interface{}
	// Stack is the stack trace from the recover.
	Stack []byte
}

RecoveredPanicError represents a recovered panic.

func (RecoveredPanicError) Error added in v0.1.2

func (p RecoveredPanicError) Error() string

Error returns the recovered panic as a string

type Runner

type Runner interface {
	// Run starts the Runner and blocks until it's done.
	Run(ctx context.Context) error
}

Runner is something that can be run and gracefully stopped.

func RunnerFunc

func RunnerFunc(runFn func(ctx context.Context) error) Runner

RunnerFunc turns a basic func into a Runner.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL