aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMatthew Holt <[email protected]>2022-03-03 10:57:55 -0700
committerMatthew Holt <[email protected]>2022-03-03 10:58:15 -0700
commitceef70dbc5543436b04a5f70749be18582f35403 (patch)
treeeb46e155dc5b79bb71d8fd8a4065b2c1eda79c66
parentf5e104944ea48e776580a0a9ebbd02fca33d659f (diff)
downloadcaddy-ceef70dbc5543436b04a5f70749be18582f35403.tar.gz
caddy-ceef70dbc5543436b04a5f70749be18582f35403.zip
core: Retry dynamic config load if error or no-op (#4603)
Also fix ineffectual assignment (unrelated)
-rw-r--r--admin.go3
-rw-r--r--caddy.go41
2 files changed, 28 insertions, 16 deletions
diff --git a/admin.go b/admin.go
index 11efc683b..8558cee1c 100644
--- a/admin.go
+++ b/admin.go
@@ -262,7 +262,7 @@ func (admin *AdminConfig) newAdminHandler(addr NetworkAddress, remote bool) admi
// provisionAdminRouters provisions all the router modules
// in the admin.api namespace that need provisioning.
-func (admin AdminConfig) provisionAdminRouters(ctx Context) error {
+func (admin *AdminConfig) provisionAdminRouters(ctx Context) error {
for _, router := range admin.routers {
provisioner, ok := router.(Provisioner)
if !ok {
@@ -277,6 +277,7 @@ func (admin AdminConfig) provisionAdminRouters(ctx Context) error {
// We no longer need the routers once provisioned, allow for GC
admin.routers = nil
+
return nil
}
diff --git a/caddy.go b/caddy.go
index 364392401..661d0b0c3 100644
--- a/caddy.go
+++ b/caddy.go
@@ -504,20 +504,29 @@ func finishSettingUp(ctx Context, cfg *Config) error {
if cfg.Admin.Config.LoadDelay > 0 {
go func() {
- timer := time.NewTimer(time.Duration(cfg.Admin.Config.LoadDelay))
- select {
- case <-timer.C:
- loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
- if err != nil {
- Log().Error("loading dynamic config failed", zap.Error(err))
- return
+ // the loop is here only to iterate if there is an error or a no-op config load,
+ // in which case we simply wait the delay and try again
+ for {
+ timer := time.NewTimer(time.Duration(cfg.Admin.Config.LoadDelay))
+ select {
+ case <-timer.C:
+ loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
+ if err != nil {
+ Log().Error("failed loading dynamic config; will retry", zap.Error(err))
+ continue
+ }
+ if loadedConfig == nil {
+ Log().Info("dynamically-loaded config was nil; will retry")
+ continue
+ }
+ runLoadedConfig(loadedConfig)
+ case <-ctx.Done():
+ if !timer.Stop() {
+ <-timer.C
+ }
+ Log().Info("stopping dynamic config loading")
}
- runLoadedConfig(loadedConfig)
- case <-ctx.Done():
- if !timer.Stop() {
- <-timer.C
- }
- Log().Info("stopping dynamic config loading")
+ break
}
}()
} else {
@@ -534,8 +543,10 @@ func finishSettingUp(ctx Context, cfg *Config) error {
return nil
}
-// ConfigLoader is a type that can load a Caddy config. The
-// returned config must be valid Caddy JSON.
+// ConfigLoader is a type that can load a Caddy config. If
+// the return value is non-nil, it must be valid Caddy JSON;
+// if nil or with non-nil error, it is considered to be a
+// no-op load and may be retried later.
type ConfigLoader interface {
LoadConfig(Context) ([]byte, error)
}