Help us shape the future of Go! Take the 2026 Go Developer Survey

graceland

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2020 License: MIT Imports: 4 Imported by: 3

README

graceland

Graceful shutdown for multi-routine Go programs.

The Mississippi Delta was shining like a national guitar 🎸

Usage

import (
    "net/http"

    "github.com/psiemens/graceland"
)

// Server implements the graceland.Routine interface.
type Server struct {
	server *http.Server
}

func NewServer() *Server {
	server := &http.Server{
		Addr: ":8080",
		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			fmt.Fprint(w, "Hello, World!")
		}),
	}

	return &Server{server: server}
}

func (h *Server) Start() error {
	err := h.server.ListenAndServe()
	if errors.Is(err, http.ErrServerClosed) {
		return nil
	}

	return err
}

func (h *Server) Stop() {
	h.server.Shutdown(context.Background())
}

// Worker implements the graceland.Routine interface.
type Worker struct {
	ticker *time.Ticker
	done   chan bool
}

func NewWorker() *Worker {
	return &Worker{
		ticker: time.NewTicker(time.Second),
		done:   make(chan bool, 1),
	}
}

func (t *Worker) Start() error {
	for {
		select {
		case <-t.ticker.C:
			// do work
		case <-t.done:
			return nil
		}
	}
}

func (t *Worker) Stop() {
	t.done <- true
}

func main() {
	// create a new routine group
	g := graceland.NewGroup()

	server := NewServer()
	worker := NewWorker()

	// add server and worker to group
	g.Add(server)
	g.Add(worker)

	// stop group after 3 seconds
	go func() {
		time.Sleep(time.Second * 3)
		g.Stop()
	}()

	// start group and block until shutdown
	err := g.Start()
	if err != nil {
		fmt.Printf("Shut down with error: %s\n", err.Error())
		return
	}

	fmt.Print("Shut down with no error\n")
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Group

type Group struct {
	// contains filtered or unexported fields
}

A Group synchronizes the startup and shutdown behaviour of multiple routines.

All registered routines start running simultaneously. If any routine stops, all other routines in the group are gracefully shut down.

Similarly, a call to Stop will gracefully shut down all routines in the group.

A group is thread-safe in the sense that it can run multiple routines and track their statuses without data races.

func NewGroup

func NewGroup() *Group

NewGroup creates a new routine group.

func (*Group) Add

func (g *Group) Add(r Routine)

Add adds a routine to the group.

func (*Group) Start

func (g *Group) Start() error

Start starts all routines in the group.

This function blocks until all routines in the group have finished running.

If one or more routines stop early and produce an error, this function returns with the first error that was captured.

This function also captures any SIGINT, SIGQUIT or SIGTERM signals received from the host environment. After receiving any of these signals, all routines in the group are shut down gracefully.

func (*Group) Stop

func (g *Group) Stop()

Stop gracefully shuts down all routines in the group.

In any scenario, a group guarantees that each routine's Stop function is called at most once.

type Routine

type Routine interface {
	// Start starts the routine and blocks until it completes.
	// This function will return an error if the routine stops unexpectedly.
	Start() error
	// Stop stops the running routine.
	// Calling this function will cause Start to return without an error.
	Stop()
}

A Routine is a long-running task that can be started and stopped.

Jump to

Keyboard shortcuts

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