mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-25 17:56:34 +08:00
startup: Only run commands at first startup
We had to hack some special support into the server and caddy packages for this. There are some middlewares which should only execute commands when the original parent process first starts up. For example, someone using the startup directive to start a backend service would not expect the command to be executed every time the config was reloaded or changed - only once when they first started the original caddy process. This commit adds FirstStartup to the virtualhost config
This commit is contained in:
parent
76ec785e87
commit
5cced604e4
|
@ -71,6 +71,10 @@ var (
|
|||
// index in the list of inherited file descriptors. This
|
||||
// variable is not safe for concurrent access.
|
||||
loadedGob caddyfileGob
|
||||
|
||||
// startedBefore should be set to true if caddy has been
|
||||
// started at least once.
|
||||
startedBefore bool
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -128,6 +132,7 @@ func Start(cdyfile Input) (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
startedBefore = true
|
||||
|
||||
// Close remaining file descriptors we may have inherited that we don't need
|
||||
if IsRestart() {
|
||||
|
@ -203,6 +208,18 @@ func startServers(groupings bindingGroup) error {
|
|||
wg.Add(1)
|
||||
go func(s *server.Server, ln server.ListenerFile) {
|
||||
defer wg.Done()
|
||||
|
||||
// run startup functions that should only execute when
|
||||
// the original parent process is starting.
|
||||
if !IsRestart() && !startedBefore {
|
||||
err := s.RunFirstStartupFuncs()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// start the server
|
||||
if ln != nil {
|
||||
errChan <- s.Serve(ln)
|
||||
} else {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
// Startup registers a startup callback to execute during server start.
|
||||
func Startup(c *Controller) (middleware.Middleware, error) {
|
||||
return nil, registerCallback(c, &c.Startup)
|
||||
return nil, registerCallback(c, &c.FirstStartup)
|
||||
}
|
||||
|
||||
// Shutdown registers a shutdown callback to execute during process exit.
|
||||
|
|
|
@ -45,7 +45,7 @@ func TestStartup(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("Expected no errors, got: %v", err)
|
||||
}
|
||||
err = c.Startup[0]()
|
||||
err = c.FirstStartup[0]()
|
||||
if err != nil && !test.shouldExecutionErr {
|
||||
t.Errorf("Test %d recieved an error of:\n%v", i, err)
|
||||
}
|
||||
|
|
|
@ -26,11 +26,21 @@ type Config struct {
|
|||
// Middleware stack; map of path scope to middleware -- TODO: Support path scope?
|
||||
Middleware map[string][]middleware.Middleware
|
||||
|
||||
// Functions (or methods) to execute at server start; these
|
||||
// are executed before any parts of the server are configured,
|
||||
// and the functions are blocking
|
||||
// Startup is a list of functions (or methods) to execute at
|
||||
// server startup and restart; these are executed before any
|
||||
// parts of the server are configured, and the functions are
|
||||
// blocking. These are good for setting up middlewares and
|
||||
// starting goroutines.
|
||||
Startup []func() error
|
||||
|
||||
// FirstStartup is like Startup but these functions only execute
|
||||
// during the initial startup, not on subsequent restarts.
|
||||
//
|
||||
// (Note: The server does not ever run these on its own; it is up
|
||||
// to the calling application to do so, and do so only once, as the
|
||||
// server itself has no notion whether it's a restart or not.)
|
||||
FirstStartup []func() error
|
||||
|
||||
// Functions (or methods) to execute when the server quits;
|
||||
// these are executed in response to SIGINT and are blocking
|
||||
Shutdown []func() error
|
||||
|
|
|
@ -371,6 +371,23 @@ func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// RunFirstStartupFuncs runs all of the server's FirstStartup
|
||||
// callback functions unless one of them returns an error first.
|
||||
// It is up the caller's responsibility to call this only once and
|
||||
// at the correct time. The functions here should not be executed
|
||||
// at restarts or where the user does not explicitly start a new
|
||||
// instance of the server.
|
||||
func (s *Server) RunFirstStartupFuncs() error {
|
||||
for _, vh := range s.vhosts {
|
||||
for _, f := range vh.config.FirstStartup {
|
||||
if err := f(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
|
||||
// connections. It's used by ListenAndServe and ListenAndServeTLS so
|
||||
// dead TCP connections (e.g. closing laptop mid-download) eventually
|
||||
|
|
Loading…
Reference in New Issue
Block a user