diff options
author | 王清雨 <[email protected]> | 2021-07-29 05:39:08 +0800 |
---|---|---|
committer | GitHub <[email protected]> | 2021-07-28 15:39:08 -0600 |
commit | c131339c5cda3a541223fde4a714aab55de13b9a (patch) | |
tree | 8f5e82cf3596bb78497266e287e7f81e6ef35cc5 /caddy.go | |
parent | b6f51254ea2dcb29dde0ffb4076802505a43ace1 (diff) | |
download | caddy-c131339c5cda3a541223fde4a714aab55de13b9a.tar.gz caddy-c131339c5cda3a541223fde4a714aab55de13b9a.zip |
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 <[email protected]>
* Update caddy.go
Co-authored-by: Matt Holt <[email protected]>
* Update admin.go
Co-authored-by: Francis Lavoie <[email protected]>
* 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 <[email protected]>
Co-authored-by: Matt Holt <[email protected]>
Co-authored-by: Francis Lavoie <[email protected]>
Diffstat (limited to 'caddy.go')
-rw-r--r-- | caddy.go | 44 |
1 files changed, 32 insertions, 12 deletions
@@ -268,8 +268,9 @@ func unsyncedDecodeAndRun(cfgJSON []byte, allowPersist bool) error { newCfg != nil && newCfg.Admin != nil && newCfg.Admin.Config != nil && - newCfg.Admin.Config.LoadRaw != nil { - return fmt.Errorf("recursive config loading detected: pulled configs cannot pull other configs") + newCfg.Admin.Config.LoadRaw != nil && + newCfg.Admin.Config.LoadInterval <= 0 { + return fmt.Errorf("recursive config loading detected: pulled configs cannot pull other configs without positive load_interval") } // run the new config and start all its apps @@ -480,23 +481,42 @@ func finishSettingUp(ctx Context, cfg *Config) error { if err != nil { return fmt.Errorf("loading config loader module: %s", err) } - loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx) - if err != nil { - return fmt.Errorf("loading dynamic config from %T: %v", val, err) - } - - // do this in a goroutine so current config can finish being loaded; otherwise deadlock - go func() { - Log().Info("applying dynamically-loaded config", zap.String("loader_module", val.(Module).CaddyModule().ID.Name())) + runLoadedConfig := func(config []byte) { + Log().Info("applying dynamically-loaded config", zap.String("loader_module", val.(Module).CaddyModule().ID.Name()), zap.Int("pull_interval", int(cfg.Admin.Config.LoadInterval))) currentCfgMu.Lock() - err := unsyncedDecodeAndRun(loadedConfig, false) + err := unsyncedDecodeAndRun(config, false) currentCfgMu.Unlock() if err == nil { Log().Info("dynamically-loaded config applied successfully") } else { Log().Error("running dynamically-loaded config failed", zap.Error(err)) } - }() + } + if cfg.Admin.Config.LoadInterval > 0 { + go func() { + select { + // if LoadInterval is positive, will wait for the interval and then run with new config + case <-time.After(time.Duration(cfg.Admin.Config.LoadInterval)): + loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx) + if err != nil { + Log().Error("loading dynamic config failed", zap.Error(err)) + return + } + runLoadedConfig(loadedConfig) + case <-ctx.Done(): + return + } + }() + } else { + // if no LoadInterval is provided, will load config synchronously + loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx) + if err != nil { + return fmt.Errorf("loading dynamic config from %T: %v", val, err) + } + // do this in a goroutine so current config can finish being loaded; otherwise deadlock + go runLoadedConfig(loadedConfig) + } + } return nil |