From 373372ac59bf59fe912e73ec4a6ef6e87e20af7f Mon Sep 17 00:00:00 2001 From: yusing Date: Fri, 9 Jan 2026 21:48:35 +0800 Subject: [PATCH] refactor(homepage/icon): check service health before fetching icons and add retry logic The icon fetching logic now checks if the target service is healthy before attempting to fetch icons. If the health monitor reports an unhealthy status, the function returns HTTP 503 Service Unavailable instead of proceeding. Additionally, the icon cache lookup now includes infinite retry logic with a 15-second backoff interval, improving resilience during transient service outages. Previously, failed lookups would not be retried. The `route` interface was extended with a `HealthMonitor()` method to support the health check functionality. --- internal/homepage/icons/fetch/fetch.go | 6 +++++- internal/homepage/icons/fetch/route.go | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/homepage/icons/fetch/fetch.go b/internal/homepage/icons/fetch/fetch.go index ef5b34fa..23fe03e6 100644 --- a/internal/homepage/icons/fetch/fetch.go +++ b/internal/homepage/icons/fetch/fetch.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "math" "net/http" "net/url" "slices" @@ -163,6 +164,9 @@ func FindIcon(ctx context.Context, r route, uri string, variant icons.Variant) ( } } if r, ok := r.(httpRoute); ok { + if mon := r.HealthMonitor(); mon != nil && !mon.Status().Good() { + return FetchResultWithErrorf(http.StatusServiceUnavailable, "service unavailable") + } // fallback to parse html return findIconSlowCached(context.WithValue(ctx, "route", contextValue{r: r, uri: uri}), r.Key()) } @@ -172,7 +176,7 @@ func FindIcon(ctx context.Context, r route, uri string, variant icons.Variant) ( var findIconSlowCached = cache.NewKeyFunc(func(ctx context.Context, key string) (Result, error) { v := ctx.Value("route").(contextValue) return findIconSlow(ctx, v.r, v.uri, nil) -}).WithMaxEntries(200).Build() // no retries, no ttl +}).WithMaxEntries(200).WithRetriesConstantBackoff(math.MaxInt, 15*time.Second).Build() // infinite retries, 15 seconds interval func findIconSlow(ctx context.Context, r httpRoute, uri string, stack []string) (Result, error) { select { diff --git a/internal/homepage/icons/fetch/route.go b/internal/homepage/icons/fetch/route.go index 246561ea..ccd16b7c 100644 --- a/internal/homepage/icons/fetch/route.go +++ b/internal/homepage/icons/fetch/route.go @@ -4,6 +4,7 @@ import ( "net/http" nettypes "github.com/yusing/godoxy/internal/net/types" + "github.com/yusing/godoxy/internal/types" "github.com/yusing/goutils/pool" ) @@ -12,6 +13,7 @@ type route interface { ProviderName() string References() []string TargetURL() *nettypes.URL + HealthMonitor() types.HealthMonitor } type httpRoute interface {