diff --git a/pkg/hold/admin/handlers_relays.go b/pkg/hold/admin/handlers_relays.go index f75a94d..693f92e 100644 --- a/pkg/hold/admin/handlers_relays.go +++ b/pkg/hold/admin/handlers_relays.go @@ -1,7 +1,6 @@ package admin import ( - "fmt" "log/slog" "net/http" "net/url" @@ -85,71 +84,87 @@ func (ui *AdminUI) handleRelayStatus(w http.ResponseWriter, r *http.Request) { ui.renderTemplate(w, "partials/relay_status.html", view) } -// handleRelayCrawl requests crawl from a single relay. -func (ui *AdminUI) handleRelayCrawl(w http.ResponseWriter, r *http.Request) { - if err := r.ParseForm(); err != nil { - setFlash(w, r, "error", "Invalid form data") - http.Redirect(w, r, "/admin#relays", http.StatusFound) - return - } - - relayURL := r.FormValue("url") - if relayURL == "" { - setFlash(w, r, "error", "Missing relay URL") - http.Redirect(w, r, "/admin#relays", http.StatusFound) - return - } - - if err := atproto.RequestCrawl(relayURL, ui.config.PublicURL); err != nil { - slog.Warn("Failed to request crawl from relay", "relay", relayURL, "error", err) - setFlash(w, r, "error", "Crawl request failed: "+err.Error()) - } else { - slog.Info("Crawl requested via admin panel", "relay", relayURL) - setFlash(w, r, "success", "Crawl requested from "+relayURL) - } - - http.Redirect(w, r, "/admin#relays", http.StatusFound) +// RelayCrawlResultView is the data for a single relay crawl result row. +type RelayCrawlResultView struct { + Name string + URL string + Success bool + Error string } -// handleRelayCrawlAll requests crawl from all known relays. +// handleRelayCrawl requests crawl from a single relay and returns an HTMX partial. +func (ui *AdminUI) handleRelayCrawl(w http.ResponseWriter, r *http.Request) { + relayURL := r.URL.Query().Get("url") + relayName := r.URL.Query().Get("name") + if relayURL == "" { + http.Error(w, "Missing relay URL", http.StatusBadRequest) + return + } + + err := atproto.RequestCrawl(relayURL, ui.config.PublicURL) + + view := RelayCrawlResultView{ + Name: relayName, + URL: relayURL, + Success: err == nil, + } + if err != nil { + view.Error = err.Error() + slog.Warn("Failed to request crawl from relay", "relay", relayURL, "error", err) + } else { + slog.Info("Crawl requested via admin panel", "relay", relayURL) + } + + ui.renderTemplate(w, "partials/relay_crawl_result.html", view) +} + +// handleRelayCrawlAll requests crawl from all known relays and returns HTMX partials. func (ui *AdminUI) handleRelayCrawlAll(w http.ResponseWriter, r *http.Request) { relays := atproto.KnownRelays - var ( - wg sync.WaitGroup - mu sync.Mutex - successes int - failures int - ) + type result struct { + relay atproto.KnownRelay + err error + } - for _, relay := range relays { + results := make([]result, len(relays)) + var wg sync.WaitGroup + + for i, relay := range relays { wg.Add(1) - go func(relay atproto.KnownRelay) { + go func(i int, relay atproto.KnownRelay) { defer wg.Done() - if err := atproto.RequestCrawl(relay.URL, ui.config.PublicURL); err != nil { - slog.Warn("Failed to request crawl", "relay", relay.Name, "error", err) - mu.Lock() - failures++ - mu.Unlock() - } else { - mu.Lock() - successes++ - mu.Unlock() - } - }(relay) + err := atproto.RequestCrawl(relay.URL, ui.config.PublicURL) + results[i] = result{relay: relay, err: err} + }(i, relay) } wg.Wait() session := getSessionFromContext(r.Context()) + successes := 0 + for _, res := range results { + if res.err == nil { + successes++ + } + } slog.Info("Crawl all requested via admin panel", - "successes", successes, "failures", failures, "by", session.DID) + "successes", successes, "failures", len(relays)-successes, "by", session.DID) - if failures == 0 { - setFlash(w, r, "success", fmt.Sprintf("Crawl requested from all %d relays", successes)) - } else { - setFlash(w, r, "warning", fmt.Sprintf("Crawl: %d succeeded, %d failed", successes, failures)) + var views []RelayCrawlResultView + for _, res := range results { + v := RelayCrawlResultView{ + Name: res.relay.Name, + URL: res.relay.URL, + Success: res.err == nil, + } + if res.err != nil { + v.Error = res.err.Error() + } + views = append(views, v) } - http.Redirect(w, r, "/admin#relays", http.StatusFound) + ui.renderTemplate(w, "partials/relay_crawl_results.html", struct { + Results []RelayCrawlResultView + }{Results: views}) } diff --git a/pkg/hold/admin/templates/partials/relay_crawl_result.html b/pkg/hold/admin/templates/partials/relay_crawl_result.html new file mode 100644 index 0000000..70b82b4 --- /dev/null +++ b/pkg/hold/admin/templates/partials/relay_crawl_result.html @@ -0,0 +1,48 @@ +{{define "partials/relay_crawl_result.html"}} +
{{.URL}}
+ {{.URL}}
+ Requesting crawl from all relays...
+This may take a few seconds.
+