Skip to content

Commit a65ced4

Browse files
fix(management): reload plugins asynchronously after changes
1 parent 13f51d9 commit a65ced4

4 files changed

Lines changed: 23 additions & 10 deletions

File tree

internal/api/handlers/management/plugin_store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ func (h *Handler) installPluginFromStore(c *gin.Context, goos, goarch string) {
274274
reloadCfg := h.cfg
275275
h.mu.Unlock()
276276

277-
h.reloadConfigAfterManagementSave(c.Request.Context(), reloadCfg)
277+
h.reloadConfigAfterManagementSaveAsync(c.Request.Context(), reloadCfg)
278278
log.WithFields(log.Fields{
279279
"plugin_id": result.ID,
280280
"source_id": source.ID,

internal/api/handlers/management/plugin_store_test.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -511,12 +511,9 @@ func TestInstallPluginFromStoreOverwritesFilePreservesConfigAndReloads(t *testin
511511
"https://downloads.example/checksums.txt": []byte(hex.EncodeToString(checksum[:]) + " " + archiveName + "\n"),
512512
},
513513
}
514-
reloads := 0
514+
reloads := make(chan *config.Config, 1)
515515
h.SetConfigReloadHook(func(_ context.Context, cfg *config.Config) {
516-
reloads++
517-
if cfg != h.cfg {
518-
t.Fatalf("reload config = %p, want handler config %p", cfg, h.cfg)
519-
}
516+
reloads <- cfg
520517
})
521518

522519
rec := httptest.NewRecorder()
@@ -529,8 +526,8 @@ func TestInstallPluginFromStoreOverwritesFilePreservesConfigAndReloads(t *testin
529526
if rec.Code != http.StatusOK {
530527
t.Fatalf("status = %d, want %d; body=%s", rec.Code, http.StatusOK, rec.Body.String())
531528
}
532-
if reloads != 1 {
533-
t.Fatalf("reloads = %d, want 1", reloads)
529+
if cfg := waitForAsyncReload(t, reloads); cfg != h.cfg {
530+
t.Fatalf("reload config = %p, want handler config %p", cfg, h.cfg)
534531
}
535532
data, errRead := os.ReadFile(existingPath)
536533
if errRead != nil {

internal/api/handlers/management/plugins.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,27 @@ func (h *Handler) PatchPluginEnabled(c *gin.Context) {
215215
}
216216

217217
h.mu.Lock()
218-
defer h.mu.Unlock()
219218
ensurePluginConfigMap(h.cfg)
220219
item := h.cfg.Plugins.Configs[id]
221220
node := pluginConfigNode(item)
222221
setYAMLMappingValue(node, "enabled", boolYAMLNode(*body.Enabled))
223222
updated, errConfig := pluginInstanceConfigFromNode(node)
224223
if errConfig != nil {
224+
h.mu.Unlock()
225225
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_config", "message": errConfig.Error()})
226226
return
227227
}
228228
h.cfg.Plugins.Configs[id] = updated
229-
h.persistLocked(c)
229+
if errSave := config.SaveConfigPreserveComments(h.configFilePath, h.cfg); errSave != nil {
230+
h.mu.Unlock()
231+
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to save config: %v", errSave)})
232+
return
233+
}
234+
reloadCfg := h.cfg
235+
h.mu.Unlock()
236+
237+
h.reloadConfigAfterManagementSaveAsync(c.Request.Context(), reloadCfg)
238+
c.JSON(http.StatusOK, gin.H{"status": "ok"})
230239
}
231240

232241
// PutPluginConfig replaces plugins.configs.<id> with the request object.

internal/api/handlers/management/plugins_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ func TestPatchPluginEnabledUpdatesOnlyPluginConfig(t *testing.T) {
241241
},
242242
configFilePath: writeTestConfigFile(t),
243243
}
244+
reloads := make(chan *config.Config, 1)
245+
h.SetConfigReloadHook(func(_ context.Context, cfg *config.Config) {
246+
reloads <- cfg
247+
})
244248

245249
rec := httptest.NewRecorder()
246250
c, _ := gin.CreateTestContext(rec)
@@ -253,6 +257,9 @@ func TestPatchPluginEnabledUpdatesOnlyPluginConfig(t *testing.T) {
253257
if rec.Code != http.StatusOK {
254258
t.Fatalf("status = %d, want %d; body=%s", rec.Code, http.StatusOK, rec.Body.String())
255259
}
260+
if cfg := waitForAsyncReload(t, reloads); cfg != h.cfg {
261+
t.Fatalf("reload config = %p, want handler config %p", cfg, h.cfg)
262+
}
256263
if h.cfg.Plugins.Enabled {
257264
t.Fatal("global Plugins.Enabled changed to true")
258265
}

0 commit comments

Comments
 (0)