/stop

A halting mechanism for Go

Primary LanguageGoApache License 2.0Apache-2.0

Stop

A go library that helps you implement a halting mechanism.

Use cases

Kubernetes pods

Kubernetes provides a way to gracefully shutdown pods using a pre-stop hook; stop can be used to communicate the hook to any go application.

Methods

OS Signal

This library allows you to handle OS halting signals with either a channel or a callback.

Channel

import "github.com/noamt/stop"

signalChannel := stop.OnOSSignal()

_ = <-signalChannel
// Do stuff

Callback

import "github.com/noamt/stop"

onSignal := func() {
	// Do stuff
}

onPanic := func(r interface{}) {
	// Panic handler
}

stop.OnOSSignalCall(onSignal, onPanic)

HTTP

This library allows you to handle halting signals sent over HTTP. You can either register a handler on your own server, or start a background server on a separate port.

Handler

import (
	"net/http"
	"github.com/noamt/stop"
)

m := http.NewServeMux()
s := http.Server{Addr: ":80", Handler: m}
stop.OnHttpCall(m, func(writer http.ResponseWriter, request *http.Request) {
    // Do stuff
})

s.ListenAndServe()

Background Server

import (
	"net/http"
	"github.com/noamt/stop"
)

stop.OnHttpServerCall("localhost", 1337, func(writer http.ResponseWriter, request *http.Request) {
    // Do stuff
})

Customized command

This library uses 2 files as signals - process.stop to signal that an application needs to stop and process.stopped to signal that the application has successfully stopped.

The go application watches for the stop signal file. When executed, the stop command creates the stop signal file, and then watches for the stopped signal with a timeout. This timeout can be set using the STOP_TIMEOUT_SECONDS environment variable, and is by default 30 seconds.

Once the go application finds the stop signal, it performs all shutdown operations and creates the stopped signal.

The stop command finds the stopped signal and returns a successful exit code.

                                               ------------------
              Watch for /tmp/process.stop <--- | go application |
                           |                   ------------------
                           |
------------              \|/
| stop cmd | ---> Create /tmp/process.stop
------------               |
                           |
------------              \|/
| stop cmd | ---> Watch for /tmp/process.stopped
------------               |
                           |
                          \|/                  ------------------
                   Find /tmp/process.stop ---> | go application |
                           |                   ------------------
                           |
                          \|/                  ------------------
              Create /tmp/process.stopped <--- | go application |
                           |                   ------------------
                           |
------------              \|/
| stop cmd | <--- Find /tmp/process.stopped
------------

Usage

Application
import "github.com/noamt/stop"

stopChannel := stop.ListenForStopSignal()

_ = <-stopChannel
// Do stuff
stop.SignalThatProcessHasStopped()
Stop command
./stop