@marcel91200 / caddy Mirror · read-only / commits / c131339c
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

admin: Implement load_interval to pull config on a timer (#4246)

* feat: implement a simple timer to pull config mostly referenced to the issue re #4106 * Update admin.go use `caddy.Duration` Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * Update caddy.go Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * Update admin.go Co-authored-by: Francis Lavoie <lavofr@gmail.com> * fix: sync load config when no pull interval provided try not to make break change * fix: change PullInterval to LoadInterval * fix: change pull_interval to load_interval * Update caddy.go Co-authored-by: Matt Holt <mholt@users.noreply.github.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com> Co-authored-by: Francis Lavoie <lavofr@gmail.com>

王清雨 committed Jul 29, 2021 at 05:39 UTC c131339c5cda3a541223fde4a714aab55de13b9a
2 files changed +38 -12
admin.go
+6
@@ -109,6 +109,12 @@ type ConfigSettings struct {
109 //
110 // EXPERIMENTAL: Subject to change.
111 LoadRaw json.RawMessage `json:"load,omitempty" caddy:"namespace=caddy.config_loaders inline_key=module"`
112 +
113 + // The interval to pull config. With a non-zero value, will pull config
114 + // from config loader (eg. a http loader) with given interval.
115 + //
116 + // EXPERIMENTAL: Subject to change.
117 + LoadInterval Duration `json:"load_interval,omitempty"`
118 }
119
120 // IdentityConfig configures management of this server's identity. An identity
caddy.go
+32 -12
@@ -268,8 +268,9 @@ func unsyncedDecodeAndRun(cfgJSON []byte, allowPersist bool) error {
268 newCfg != nil &&
269 newCfg.Admin != nil &&
270 newCfg.Admin.Config != nil &&
271 - newCfg.Admin.Config.LoadRaw != nil {
272 - return fmt.Errorf("recursive config loading detected: pulled configs cannot pull other configs")
271 + newCfg.Admin.Config.LoadRaw != nil &&
272 + newCfg.Admin.Config.LoadInterval <= 0 {
273 + return fmt.Errorf("recursive config loading detected: pulled configs cannot pull other configs without positive load_interval")
274 }
275
276 // run the new config and start all its apps
@@ -480,23 +481,42 @@ func finishSettingUp(ctx Context, cfg *Config) error {
481 if err != nil {
482 return fmt.Errorf("loading config loader module: %s", err)
483 }
483 - loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
484 - if err != nil {
485 - return fmt.Errorf("loading dynamic config from %T: %v", val, err)
486 - }
487 -
488 - // do this in a goroutine so current config can finish being loaded; otherwise deadlock
489 - go func() {
490 - Log().Info("applying dynamically-loaded config", zap.String("loader_module", val.(Module).CaddyModule().ID.Name()))
484 + runLoadedConfig := func(config []byte) {
485 + Log().Info("applying dynamically-loaded config", zap.String("loader_module", val.(Module).CaddyModule().ID.Name()), zap.Int("pull_interval", int(cfg.Admin.Config.LoadInterval)))
486 currentCfgMu.Lock()
492 - err := unsyncedDecodeAndRun(loadedConfig, false)
487 + err := unsyncedDecodeAndRun(config, false)
488 currentCfgMu.Unlock()
489 if err == nil {
490 Log().Info("dynamically-loaded config applied successfully")
491 } else {
492 Log().Error("running dynamically-loaded config failed", zap.Error(err))
493 }
499 - }()
494 + }
495 + if cfg.Admin.Config.LoadInterval > 0 {
496 + go func() {
497 + select {
498 + // if LoadInterval is positive, will wait for the interval and then run with new config
499 + case <-time.After(time.Duration(cfg.Admin.Config.LoadInterval)):
500 + loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
501 + if err != nil {
502 + Log().Error("loading dynamic config failed", zap.Error(err))
503 + return
504 + }
505 + runLoadedConfig(loadedConfig)
506 + case <-ctx.Done():
507 + return
508 + }
509 + }()
510 + } else {
511 + // if no LoadInterval is provided, will load config synchronously
512 + loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx)
513 + if err != nil {
514 + return fmt.Errorf("loading dynamic config from %T: %v", val, err)
515 + }
516 + // do this in a goroutine so current config can finish being loaded; otherwise deadlock
517 + go runLoadedConfig(loadedConfig)
518 + }
519 +
520 }
521
522 return nil