mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-24 08:49:01 +01:00
OnFirstStartup and OnFinalShutdown callbacks added
OnStartup and OnShutdown callbacks now run as part of restarts, too. The startup and shutdown directives only run their commands NOT as part of restarts, as before. Some middleware that use OnStartup may need to switch to OnFirstStartup and implement OnFinalShutdown to do any cleanup as needed.
This commit is contained in:
parent
b49f65d5de
commit
15fa5cf2da
8 changed files with 73 additions and 16 deletions
40
caddy.go
40
caddy.go
|
@ -73,10 +73,12 @@ type Instance struct {
|
||||||
// servers is the list of servers with their listeners.
|
// servers is the list of servers with their listeners.
|
||||||
servers []serverListener
|
servers []serverListener
|
||||||
|
|
||||||
// these are callbacks to execute when certain events happen
|
// these callbacks execute when certain events occur
|
||||||
onStartup []func() error
|
onFirstStartup []func() error // starting, not as part of a restart
|
||||||
onRestart []func() error
|
onStartup []func() error // starting, even as part of a restart
|
||||||
onShutdown []func() error
|
onRestart []func() error // before restart commences
|
||||||
|
onShutdown []func() error // stopping, even as part of a restart
|
||||||
|
onFinalShutdown []func() error // stopping, not as part of a restart
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops all servers contained in i. It does NOT
|
// Stop stops all servers contained in i. It does NOT
|
||||||
|
@ -104,10 +106,11 @@ func (i *Instance) Stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// shutdownCallbacks executes all the shutdown callbacks of i.
|
// ShutdownCallbacks executes all the shutdown callbacks of i,
|
||||||
// An error returned from one does not stop execution of the rest.
|
// including ones that are scheduled only for the final shutdown
|
||||||
// All the errors will be returned.
|
// of i. An error returned from one does not stop execution of
|
||||||
func (i *Instance) shutdownCallbacks() []error {
|
// the rest. All the non-nil errors will be returned.
|
||||||
|
func (i *Instance) ShutdownCallbacks() []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
for _, shutdownFunc := range i.onShutdown {
|
for _, shutdownFunc := range i.onShutdown {
|
||||||
err := shutdownFunc()
|
err := shutdownFunc()
|
||||||
|
@ -115,6 +118,12 @@ func (i *Instance) shutdownCallbacks() []error {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, finalShutdownFunc := range i.onFinalShutdown {
|
||||||
|
err := finalShutdownFunc()
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +168,12 @@ func (i *Instance) Restart(newCaddyfile Input) (*Instance, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// success! stop the old instance
|
// success! stop the old instance
|
||||||
|
for _, shutdownFunc := range i.onShutdown {
|
||||||
|
err := shutdownFunc()
|
||||||
|
if err != nil {
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
}
|
||||||
i.Stop()
|
i.Stop()
|
||||||
|
|
||||||
log.Println("[INFO] Reloading complete")
|
log.Println("[INFO] Reloading complete")
|
||||||
|
@ -409,6 +424,15 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run startup callbacks
|
||||||
|
if restartFds == nil {
|
||||||
|
for _, firstStartupFunc := range inst.onFirstStartup {
|
||||||
|
err := firstStartupFunc()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, startupFunc := range inst.onStartup {
|
for _, startupFunc := range inst.onStartup {
|
||||||
err := startupFunc()
|
err := startupFunc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -29,7 +29,8 @@ type ErrorHandler struct {
|
||||||
LogFile string
|
LogFile string
|
||||||
Log *log.Logger
|
Log *log.Logger
|
||||||
LogRoller *httpserver.LogRoller
|
LogRoller *httpserver.LogRoller
|
||||||
Debug bool // if true, errors are written out to client rather than to a log
|
Debug bool // if true, errors are written out to client rather than to a log
|
||||||
|
file *os.File // a log file to close when done
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
func (h ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
|
|
@ -49,11 +49,10 @@ func setup(c *caddy.Controller) error {
|
||||||
}
|
}
|
||||||
if handler.LogRoller != nil {
|
if handler.LogRoller != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
handler.LogRoller.Filename = handler.LogFile
|
handler.LogRoller.Filename = handler.LogFile
|
||||||
|
|
||||||
writer = handler.LogRoller.GetLogWriter()
|
writer = handler.LogRoller.GetLogWriter()
|
||||||
} else {
|
} else {
|
||||||
|
handler.file = file
|
||||||
writer = file
|
writer = file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +61,14 @@ func setup(c *caddy.Controller) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// When server stops, close any open log file
|
||||||
|
c.OnShutdown(func() error {
|
||||||
|
if handler.file != nil {
|
||||||
|
handler.file.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
||||||
handler.Next = next
|
handler.Next = next
|
||||||
return handler
|
return handler
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/mholt/caddy"
|
"github.com/mholt/caddy"
|
||||||
"github.com/mholt/caddy/caddyhttp/httpserver"
|
"github.com/mholt/caddy/caddyhttp/httpserver"
|
||||||
|
@ -67,6 +68,7 @@ type Rule struct {
|
||||||
Format string
|
Format string
|
||||||
Log *log.Logger
|
Log *log.Logger
|
||||||
Roller *httpserver.LogRoller
|
Roller *httpserver.LogRoller
|
||||||
|
file *os.File // if logging to a file that needs to be closed
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -43,6 +43,7 @@ func setup(c *caddy.Controller) error {
|
||||||
rules[i].Roller.Filename = rules[i].OutputFile
|
rules[i].Roller.Filename = rules[i].OutputFile
|
||||||
writer = rules[i].Roller.GetLogWriter()
|
writer = rules[i].Roller.GetLogWriter()
|
||||||
} else {
|
} else {
|
||||||
|
rules[i].file = file
|
||||||
writer = file
|
writer = file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,16 @@ func setup(c *caddy.Controller) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// When server stops, close any open log files
|
||||||
|
c.OnShutdown(func() error {
|
||||||
|
for _, rule := range rules {
|
||||||
|
if rule.file != nil {
|
||||||
|
rule.file.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
||||||
return Logger{Next: next, Rules: rules, ErrorFunc: httpserver.DefaultErrorFunc}
|
return Logger{Next: next, Rules: rules, ErrorFunc: httpserver.DefaultErrorFunc}
|
||||||
})
|
})
|
||||||
|
|
|
@ -54,8 +54,14 @@ func (c *Controller) ServerType() string {
|
||||||
return c.instance.serverType
|
return c.instance.serverType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnFirstStartup adds fn to the list of callback functions to execute
|
||||||
|
// when the server is about to be started NOT as part of a restart.
|
||||||
|
func (c *Controller) OnFirstStartup(fn func() error) {
|
||||||
|
c.instance.onFirstStartup = append(c.instance.onFirstStartup, fn)
|
||||||
|
}
|
||||||
|
|
||||||
// OnStartup adds fn to the list of callback functions to execute
|
// OnStartup adds fn to the list of callback functions to execute
|
||||||
// when the server is about to be started.
|
// when the server is about to be started (including restarts).
|
||||||
func (c *Controller) OnStartup(fn func() error) {
|
func (c *Controller) OnStartup(fn func() error) {
|
||||||
c.instance.onStartup = append(c.instance.onStartup, fn)
|
c.instance.onStartup = append(c.instance.onStartup, fn)
|
||||||
}
|
}
|
||||||
|
@ -67,11 +73,17 @@ func (c *Controller) OnRestart(fn func() error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnShutdown adds fn to the list of callback functions to execute
|
// OnShutdown adds fn to the list of callback functions to execute
|
||||||
// when the server is about to be shut down..
|
// when the server is about to be shut down (including restarts).
|
||||||
func (c *Controller) OnShutdown(fn func() error) {
|
func (c *Controller) OnShutdown(fn func() error) {
|
||||||
c.instance.onShutdown = append(c.instance.onShutdown, fn)
|
c.instance.onShutdown = append(c.instance.onShutdown, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnFinalShutdown adds fn to the list of callback functions to execute
|
||||||
|
// when the server is about to be shut down NOT as part of a restart.
|
||||||
|
func (c *Controller) OnFinalShutdown(fn func() error) {
|
||||||
|
c.instance.onFinalShutdown = append(c.instance.onFinalShutdown, fn)
|
||||||
|
}
|
||||||
|
|
||||||
// Context gets the context associated with the instance associated with c.
|
// Context gets the context associated with the instance associated with c.
|
||||||
func (c *Controller) Context() Context {
|
func (c *Controller) Context() Context {
|
||||||
return c.instance.context
|
return c.instance.context
|
||||||
|
|
|
@ -72,7 +72,7 @@ func allShutdownCallbacks() []error {
|
||||||
var errs []error
|
var errs []error
|
||||||
instancesMu.Lock()
|
instancesMu.Lock()
|
||||||
for _, inst := range instances {
|
for _, inst := range instances {
|
||||||
errs = append(errs, inst.shutdownCallbacks()...)
|
errs = append(errs, inst.ShutdownCallbacks()...)
|
||||||
}
|
}
|
||||||
instancesMu.Unlock()
|
instancesMu.Unlock()
|
||||||
return errs
|
return errs
|
||||||
|
|
|
@ -15,12 +15,12 @@ func init() {
|
||||||
|
|
||||||
// Startup registers a startup callback to execute during server start.
|
// Startup registers a startup callback to execute during server start.
|
||||||
func Startup(c *caddy.Controller) error {
|
func Startup(c *caddy.Controller) error {
|
||||||
return registerCallback(c, c.OnStartup)
|
return registerCallback(c, c.OnFirstStartup)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown registers a shutdown callback to execute during server stop.
|
// Shutdown registers a shutdown callback to execute during server stop.
|
||||||
func Shutdown(c *caddy.Controller) error {
|
func Shutdown(c *caddy.Controller) error {
|
||||||
return registerCallback(c, c.OnShutdown)
|
return registerCallback(c, c.OnFinalShutdown)
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerCallback registers a callback function to execute by
|
// registerCallback registers a callback function to execute by
|
||||||
|
|
Loading…
Reference in a new issue