littleboss

package module
v0.0.0-...-8957d0a Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2019 License: ISC Imports: 19 Imported by: 10

README

littleboss: self-supervising Go binaries

A Go package, littleboss lets you turn your program into a a self-supervising binary. It starts itself as a child process, monitors its life cycle, reloads it if it exits, and can be instructed to replace it with a new binary.

The supervisor can open sockets for you and share them across reloads of your program, ensuring no connections are dropped.

You can install it with:

go get crawshaw.io/littleboss

Make a program use littleboss by modifying the main function:

func main() {
	lb := littleboss.New("service-name")
	lb.Run(func(ctx context.Context) {
		// main goes here, exit when <-ctx.Done()
	})
}

The service name is used to identify which program the supervisor will control.

Usage

By default the supervisor is bypassed and the program executes directly. A flag, -littleboss, is added to the binary. It can be used to start a supervised binary and manage it:

$ mybin &                     # binary runs directly, no child process
$ mybin -littleboss=start &   # supervisor is created
$ mybin2 -littleboss=reload   # child is replaced by new mybin2 process
$ mybin -littleboss=stop      # supervisor and child are shut down

Configuration

Supervisor options are baked into the binary. The littleboss struct type contains fields that can be set before calling the Run method to configure the supervisor. Options include reloading the previous binary if a reload fails, controlling how long an exiting program has to turn down its connections, and specifying exactly what flags control and are passed by littleboss.

An HTTP server example

func main() {
	lb := littleboss.New("myblog")
	flagHTTPS := lb.Listener("https", "tcp", ":443", "address")
	lb.Run(func(ctx context.Context) {
		httpMain(ctx, flagHTTPS.Listener())
	})
}

func httpMain(ctx context.Context, ln net.Listener) {
	srv := &http.Server{
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,
		IdleTimeout:  60 * time.Second,
		Handler:      blogHandler,
	}
	go func() {
		if err := srv.ServeTLS(ln, "certfile", "keyfile"); err != nil {
			if err == http.ErrServerClosed {
				return
			}
			log.Fatal(err)
		}
	}()

	<-ctx.Done()
	srv.Shutdown(ctx)
}

Documentation

Overview

Package littleboss creates self-supervising Go binaries.

A self-supervising binary starts itself as a child process. The parent process becomes a supervisor that is responsible for monitoring, managing I/O, restarting, and reloading the child.

Make a program use littleboss by modifying the main function:

func main() {
	lb := littleboss.New("service-name")
	lb.Run(func(ctx context.Context) {
		// main goes here, exit when <-ctx.Done()
	})
}

Usage

By default the supervisor is bypassed and the program executes directly. A flag, -littleboss, is added to the binary. It can be used to start a supervised binary and manage it:

$ mybin &                     # binary runs directly, no child process
$ mybin -littleboss=start &   # supervisor is created
$ mybin2 -littleboss=reload   # child is replaced by new mybin2 process
$ mybin -littleboss=stop      # supervisor and child are shut down

Configuration

Supervisor options are baked into the binary. The Littleboss struct type contains fields that can be set before calling the Run method to configure the supervisor.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ListenerFlag

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

A ListenerFlag is a flag whose value is used as a net.Listener or net.PacketConn.

An empty flag value ("") means no listener is created. For a listener on a random port, use ":0".

func (*ListenerFlag) Listener

func (lnf *ListenerFlag) Listener() net.Listener

func (*ListenerFlag) Network

func (lnf *ListenerFlag) Network() string

func (*ListenerFlag) PacketConn

func (lnf *ListenerFlag) PacketConn() net.PacketConn

func (*ListenerFlag) Set

func (lnf *ListenerFlag) Set(value string) error

func (*ListenerFlag) String

func (lnf *ListenerFlag) String() string

type Littleboss

type Littleboss struct {
	FlagSet *flag.FlagSet // used for passing flags to child, default flag.CommandLine

	Logf func(format string, args ...interface{}) // defaults to stderr

	SupervisorInit func() // executed by supervisor on Run

	Persist           bool          // if program exits, restart it
	FallbackOnFailure bool          // if program exits badly, use previous version
	LameduckTimeout   time.Duration // time to wait before forcing exit
	// contains filtered or unexported fields
}

func New

func New(serviceName string) *Littleboss

func (*Littleboss) Command

func (lb *Littleboss) Command(modeFlagName string, mode *string)

Command gives littleboss a custom command mode flag name and value.

By default littleboss creates a flag named -littleboss when Run is called, and sets its default value to "bypass". If the FlagSet is going to be processed by a non-standard flag package or the littleboss command mode is not passed as a flag at all, then this Command method can be used instead to avoid the flag creation.

This makes it possible for a program to invoke flag parsing itself, after calling New, Command, any calls to Listener, but before the call to Run.

For example:

lb := littleboss.New("myservice")
lb.Command("-mylb", pflag.String("mylb", "start", "lb command mode"))
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
lb.Run(...)

NOTE: All the flags passed to the child process are extracted from Littleboss.FlagSet. Make sure any flags defined by external flag packages have their value in the FlagSet.

func (*Littleboss) Listener

func (lb *Littleboss) Listener(flagName, network, value, usage string) *ListenerFlag

func (*Littleboss) Run

func (lb *Littleboss) Run(mainFn func(ctx context.Context))

Run starts the little boss, with mainFn as the entry point to the service. Run does not return.

Jump to

Keyboard shortcuts

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