docs and api cleanup

This commit is contained in:
Naitik Shah 2012-06-04 21:56:51 -07:00
parent 13afde4bc1
commit 7aa612785a
3 changed files with 31 additions and 15 deletions

View File

@ -64,7 +64,7 @@ func (c conn) Close() error {
return c.Conn.Close() return c.Conn.Close()
} }
// Create a new listener. // Wraps an existing File listener to provide a graceful Close() process.
func NewListener(l Listener) Listener { func NewListener(l Listener) Listener {
i := &listener{ i := &listener{
Listener: l, Listener: l,
@ -124,7 +124,7 @@ func (l *listener) Accept() (net.Conn, error) {
}, nil }, nil
} }
// Wait for signals. // Wait for signals to gracefully terminate or restart the process.
func Wait(listeners []Listener) (err error) { func Wait(listeners []Listener) (err error) {
ch := make(chan os.Signal, 2) ch := make(chan os.Signal, 2)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGUSR2) signal.Notify(ch, syscall.SIGTERM, syscall.SIGUSR2)
@ -155,7 +155,7 @@ func Wait(listeners []Listener) (err error) {
panic("not reached") panic("not reached")
} }
// Try to inherit listeners from environment variables. // Try to inherit listeners from the parent process.
func Inherit() (listeners []Listener, err error) { func Inherit() (listeners []Listener, err error) {
countStr := os.Getenv(envCountKey) countStr := os.Getenv(envCountKey)
if countStr == "" { if countStr == "" {
@ -179,12 +179,13 @@ func Inherit() (listeners []Listener, err error) {
return return
} }
// Start the Close process in the parent. // Start the Close process in the parent. This does not wait for the
// parent to close and simply sends it the TERM signal.
func CloseParent() error { func CloseParent() error {
return syscall.Kill(os.Getppid(), syscall.SIGTERM) return syscall.Kill(os.Getppid(), syscall.SIGTERM)
} }
// Restart the process passing it the given listeners. // Restart the process passing the given listeners to the new process.
func Restart(listeners []Listener) (err error) { func Restart(listeners []Listener) (err error) {
if len(listeners) == 0 { if len(listeners) == 0 {
return errors.New("restart must be given listeners.") return errors.New("restart must be given listeners.")

View File

@ -19,15 +19,15 @@ type Handler struct {
Handler http.Handler Handler http.Handler
} }
type Handlers []Handler type handlersSlice []Handler
var ( var (
verbose = flag.Bool("gracehttp.log", true, "Enable logging.") verbose = flag.Bool("gracehttp.log", true, "Enable logging.")
ErrUnexpectedListenersCount = errors.New("unexpected listeners count") errListenersCount = errors.New("unexpected listeners count")
) )
// Creates new listeners for all the given addresses. // Creates new listeners for all the given addresses.
func (handlers Handlers) newListeners() ([]grace.Listener, error) { func (handlers handlersSlice) newListeners() ([]grace.Listener, error) {
listeners := make([]grace.Listener, len(handlers)) listeners := make([]grace.Listener, len(handlers))
for index, pair := range handlers { for index, pair := range handlers {
addr, err := net.ResolveTCPAddr("tcp", pair.Addr) addr, err := net.ResolveTCPAddr("tcp", pair.Addr)
@ -45,9 +45,9 @@ func (handlers Handlers) newListeners() ([]grace.Listener, error) {
} }
// Serve on the given listeners and wait for signals. // Serve on the given listeners and wait for signals.
func (handlers Handlers) serveWait(listeners []grace.Listener) error { func (handlers handlersSlice) serveWait(listeners []grace.Listener) error {
if len(handlers) != len(listeners) { if len(handlers) != len(listeners) {
return ErrUnexpectedListenersCount return errListenersCount
} }
errch := make(chan error, len(listeners)+1) // listeners + grace.Wait errch := make(chan error, len(listeners)+1) // listeners + grace.Wait
for i, l := range listeners { for i, l := range listeners {
@ -71,11 +71,11 @@ func (handlers Handlers) serveWait(listeners []grace.Listener) error {
return <-errch return <-errch
} }
// Serve will listen on the given address. It will also wait for a // Serve will serve the given pairs of addresses and listeners and
// SIGUSR2 signal and will restart the server passing the active listener // will monitor for signals allowing for graceful termination (SIGTERM)
// to the new process and avoid dropping active connections. // or restart (SIGUSR2).
func Serve(givenHandlers ...Handler) error { func Serve(givenHandlers ...Handler) error {
handlers := Handlers(givenHandlers) handlers := handlersSlice(givenHandlers)
listeners, err := grace.Inherit() listeners, err := grace.Inherit()
if err == nil { if err == nil {
err = grace.CloseParent() err = grace.CloseParent()

15
readme.md Normal file
View File

@ -0,0 +1,15 @@
go.grace
========
Package grace provides a library that makes it easy to build socket
based servers that can be gracefully terminated & restarted (that is,
without dropping any connections).
Demo HTTP Server with graceful termination and restart:
https://github.com/nshah/go.grace/blob/master/gracedemo/demo.go
http level graceful termination and restart:
http://go.pkgdoc.org/github.com/nshah/go.grace/gracehttp
net.Listener level graceful termination and restart:
http://go.pkgdoc.org/github.com/nshah/go.grace