Skip to content

Commit 4204858

Browse files
rdimitrovclaude
andauthored
Add API endpoint to refresh the registry cache (#5268)
Adds POST /api/v1beta/registry/{name}/refresh so API clients (e.g. the UI) can force a refresh of the server-side registry cache without restarting thv serve or waiting for the 1-hour TTL. Mirrors the CLI's `thv registry list --refresh` behavior: type-asserts to CachedAPIRegistryProvider and calls ForceRefresh(). Closes #5266 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8a3e9a8 commit 4204858

5 files changed

Lines changed: 424 additions & 0 deletions

File tree

docs/server/docs.go

Lines changed: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/server/swagger.json

Lines changed: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/server/swagger.yaml

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/v1/registry.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ func RegistryRouter(serveMode bool) http.Handler {
376376
r.Get("/{name}", routes.getRegistry)
377377
r.Put("/{name}", routes.updateRegistry)
378378
r.Delete("/{name}", routes.removeRegistry)
379+
r.Post("/{name}/refresh", routes.refreshRegistry)
379380

380381
// Add nested routes for servers within a registry
381382
r.Route("/{name}/servers", func(r chi.Router) {
@@ -518,6 +519,51 @@ func (rr *RegistryRoutes) getRegistry(w http.ResponseWriter, r *http.Request) {
518519
}
519520
}
520521

522+
// refreshRegistry
523+
//
524+
// @Summary Refresh registry cache
525+
// @Description Force a refresh of the server-side registry cache for the default registry
526+
// @Tags registry
527+
// @Produce json
528+
// @Param name path string true "Registry name (must be 'default')"
529+
// @Success 200 {object} map[string]string "Registry refreshed"
530+
// @Failure 404 {string} string "Not Found"
531+
// @Failure 500 {string} string "Internal Server Error"
532+
// @Failure 503 {object} registryErrorResponse "Registry authentication required or upstream registry unavailable"
533+
// @Router /api/v1beta/registry/{name}/refresh [post]
534+
func (rr *RegistryRoutes) refreshRegistry(w http.ResponseWriter, r *http.Request) {
535+
name := chi.URLParam(r, "name")
536+
537+
// Only "default" registry is supported currently
538+
if name != defaultRegistryName {
539+
http.Error(w, "Registry not found", http.StatusNotFound)
540+
return
541+
}
542+
543+
provider, ok := rr.getCurrentProvider(w)
544+
if !ok {
545+
return
546+
}
547+
548+
if cached, ok := provider.(*regpkg.CachedAPIRegistryProvider); ok {
549+
if err := cached.ForceRefresh(); err != nil {
550+
if writeProviderError(w, err) {
551+
return
552+
}
553+
slog.Error("failed to refresh registry", "error", err)
554+
http.Error(w, "Failed to refresh registry", http.StatusInternalServerError)
555+
return
556+
}
557+
}
558+
559+
w.Header().Set("Content-Type", "application/json")
560+
if err := json.NewEncoder(w).Encode(map[string]string{"status": "refreshed"}); err != nil {
561+
slog.Error("failed to encode response", "error", err)
562+
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
563+
return
564+
}
565+
}
566+
521567
// updateRegistry
522568
//
523569
// @Summary Update registry configuration

0 commit comments

Comments
 (0)