Skip to content

Commit 1d0551a

Browse files
committed
feat(config): improve config reload handling and introduce async management save hook
- Refactored `ConfigReloadHook` to use `reloadConfigFromWatcher` for consistency. - Added async `reloadConfigAfterManagementSaveAsync` to handle post-save operations. - Introduced `ReloadConfigIfChanged` in watcher for manual trigger support. - Enhanced config reload paths to separate auth synthesis from standard updates. - Updated `applyConfigUpdate` logic to allow more granular reload behaviors. Closes: router-for-me#3235
1 parent 052f193 commit 1d0551a

6 files changed

Lines changed: 49 additions & 4 deletions

File tree

internal/api/handlers/management/handler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,13 @@ func (h *Handler) persistLocked(c *gin.Context) bool {
411411
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to save config: %v", err)})
412412
return false
413413
}
414+
snapshot := h.reloadSnapshotConfigLocked()
414415
c.JSON(http.StatusOK, gin.H{"status": "ok"})
416+
var reqCtx context.Context
417+
if c != nil && c.Request != nil {
418+
reqCtx = c.Request.Context()
419+
}
420+
h.reloadConfigAfterManagementSaveAsync(reqCtx, snapshot)
415421
return true
416422
}
417423

internal/watcher/config_reload.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ func (w *Watcher) scheduleConfigReload() {
4040
})
4141
}
4242

43+
// ReloadConfigIfChanged runs the same config reload path used by filesystem events.
44+
func (w *Watcher) ReloadConfigIfChanged() {
45+
if w == nil {
46+
return
47+
}
48+
w.reloadConfigIfChanged()
49+
}
50+
4351
func (w *Watcher) reloadConfigIfChanged() {
4452
data, err := os.ReadFile(w.configPath)
4553
if err != nil {

sdk/cliproxy/builder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ func (b *Builder) Build() (*Service, error) {
289289
service.serverOptions = append(service.serverOptions,
290290
api.WithPostAuthPersistHook(service.runtimeAuthSyncHook()),
291291
api.WithPluginHost(pluginHost),
292-
api.WithConfigReloadHook(func(ctx context.Context, cfg *config.Config) {
293-
service.applyConfigUpdate(cfg)
292+
api.WithConfigReloadHook(func(_ context.Context, _ *config.Config) {
293+
service.reloadConfigFromWatcher()
294294
}),
295295
)
296296
return service, nil

sdk/cliproxy/service.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,14 @@ func (s *Service) tryRegisterPluginModelsForAuth(ctx context.Context, a *coreaut
10971097
}
10981098

10991099
func (s *Service) applyConfigUpdate(newCfg *config.Config) {
1100+
s.applyConfigUpdateWithAuthSynthesis(newCfg, true)
1101+
}
1102+
1103+
func (s *Service) applyWatcherConfigUpdate(newCfg *config.Config) {
1104+
s.applyConfigUpdateWithAuthSynthesis(newCfg, false)
1105+
}
1106+
1107+
func (s *Service) applyConfigUpdateWithAuthSynthesis(newCfg *config.Config, synthesizeConfigAuths bool) {
11001108
if s == nil {
11011109
return
11021110
}
@@ -1190,10 +1198,19 @@ func (s *Service) applyConfigUpdate(newCfg *config.Config) {
11901198
auths: auths,
11911199
})
11921200
ctx := coreauth.WithSkipPersist(context.Background())
1193-
s.registerConfigAPIKeyAuths(ctx, newCfg)
1201+
if synthesizeConfigAuths {
1202+
s.registerConfigAPIKeyAuths(ctx, newCfg)
1203+
}
11941204
s.syncPluginRuntime(ctx)
11951205
}
11961206

1207+
func (s *Service) reloadConfigFromWatcher() bool {
1208+
if s == nil || s.watcher == nil {
1209+
return false
1210+
}
1211+
return s.watcher.ReloadConfigIfChanged()
1212+
}
1213+
11971214
func (s *Service) registerConfigAPIKeyAuths(ctx context.Context, cfg *config.Config) {
11981215
if s == nil || s.coreManager == nil || cfg == nil {
11991216
return
@@ -1442,6 +1459,7 @@ func (s *Service) Run(ctx context.Context) error {
14421459
if errLoad := s.coreManager.Load(ctx); errLoad != nil {
14431460
log.Warnf("failed to load auth store: %v", errLoad)
14441461
}
1462+
s.registerConfigAPIKeyAuths(coreauth.WithSkipPersist(ctx), s.cfg)
14451463
}
14461464

14471465
if !homeEnabled {
@@ -1532,7 +1550,7 @@ func (s *Service) Run(ctx context.Context) error {
15321550

15331551
if !homeEnabled {
15341552
var watcherWrapper *WatcherWrapper
1535-
reloadCallback := func(newCfg *config.Config) { s.applyConfigUpdate(newCfg) }
1553+
reloadCallback := func(newCfg *config.Config) { s.applyWatcherConfigUpdate(newCfg) }
15361554

15371555
watcherWrapper, errCreate := s.watcherFactory(s.configPath, s.cfg.AuthDir, reloadCallback)
15381556
if errCreate != nil {

sdk/cliproxy/types.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type WatcherWrapper struct {
9797
dispatchRuntimeUpdate func(update watcher.AuthUpdate) bool
9898
dispatchPersistedAuth func(update watcher.AuthUpdate) bool
9999
setPluginAuthParser func(parser PluginAuthParser)
100+
reloadConfigIfChanged func()
100101
}
101102

102103
// Start proxies to the underlying watcher Start implementation.
@@ -123,6 +124,15 @@ func (w *WatcherWrapper) SetConfig(cfg *config.Config) {
123124
w.setConfig(cfg)
124125
}
125126

127+
// ReloadConfigIfChanged asks the underlying watcher to reload config from disk.
128+
func (w *WatcherWrapper) ReloadConfigIfChanged() bool {
129+
if w == nil || w.reloadConfigIfChanged == nil {
130+
return false
131+
}
132+
w.reloadConfigIfChanged()
133+
return true
134+
}
135+
126136
// SetPluginAuthParser updates the plugin auth parser used by the watcher.
127137
func (w *WatcherWrapper) SetPluginAuthParser(parser PluginAuthParser) {
128138
if w == nil || w.setPluginAuthParser == nil {

sdk/cliproxy/watcher.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,8 @@ func defaultWatcherFactory(configPath, authDir string, reload func(*config.Confi
3737
setPluginAuthParser: func(parser PluginAuthParser) {
3838
w.SetPluginAuthParser(parser)
3939
},
40+
reloadConfigIfChanged: func() {
41+
w.ReloadConfigIfChanged()
42+
},
4043
}, nil
4144
}

0 commit comments

Comments
 (0)