core: Retry dynamic config load if error or no-op (#4603)

Also fix ineffectual assignment (unrelated)
This commit is contained in:
Matthew Holt 2022-03-03 10:57:55 -07:00
parent f5e104944e
commit ceef70dbc5
No known key found for this signature in database
GPG Key ID: 2A349DD577D586A5
2 changed files with 28 additions and 16 deletions

View File

@ -262,7 +262,7 @@ func (admin *AdminConfig) newAdminHandler(addr NetworkAddress, remote bool) admi
// provisionAdminRouters provisions all the router modules // provisionAdminRouters provisions all the router modules
// in the admin.api namespace that need provisioning. // 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 { for _, router := range admin.routers {
provisioner, ok := router.(Provisioner) provisioner, ok := router.(Provisioner)
if !ok { if !ok {
@ -277,6 +277,7 @@ func (admin AdminConfig) provisionAdminRouters(ctx Context) error {
// We no longer need the routers once provisioned, allow for GC // We no longer need the routers once provisioned, allow for GC
admin.routers = nil admin.routers = nil
return nil return nil
} }

View File

@ -504,13 +504,20 @@ func finishSettingUp(ctx Context, cfg *Config) error {
if cfg.Admin.Config.LoadDelay > 0 { if cfg.Admin.Config.LoadDelay > 0 {
go func() { go func() {
// 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)) timer := time.NewTimer(time.Duration(cfg.Admin.Config.LoadDelay))
select { select {
case <-timer.C: case <-timer.C:
loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx) loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
if err != nil { if err != nil {
Log().Error("loading dynamic config failed", zap.Error(err)) Log().Error("failed loading dynamic config; will retry", zap.Error(err))
return continue
}
if loadedConfig == nil {
Log().Info("dynamically-loaded config was nil; will retry")
continue
} }
runLoadedConfig(loadedConfig) runLoadedConfig(loadedConfig)
case <-ctx.Done(): case <-ctx.Done():
@ -519,6 +526,8 @@ func finishSettingUp(ctx Context, cfg *Config) error {
} }
Log().Info("stopping dynamic config loading") Log().Info("stopping dynamic config loading")
} }
break
}
}() }()
} else { } else {
// if no LoadDelay is provided, will load config synchronously // if no LoadDelay is provided, will load config synchronously
@ -534,8 +543,10 @@ func finishSettingUp(ctx Context, cfg *Config) error {
return nil return nil
} }
// ConfigLoader is a type that can load a Caddy config. The // ConfigLoader is a type that can load a Caddy config. If
// returned config must be valid Caddy JSON. // 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 { type ConfigLoader interface {
LoadConfig(Context) ([]byte, error) LoadConfig(Context) ([]byte, error)
} }