fix: bypass Wails RPC entirely for local search via HTTP endpoint

Both SearchLocal RPC and Wails events were blocked by Wails v2's
Go call serialization. When the indexer or other Go calls were
in-flight, even a 1ms Go function couldn't return to JS.

New approach: registered /api/search-local as an HTTP handler on
the Wails asset server. The frontend fetches it directly via
fetch() — this runs on Go's HTTP server goroutine pool, completely
independent of Wails RPC serialization.

The fetch completes in milliseconds regardless of what other Go
calls are queued. The full Search() pipeline still runs via Wails
RPC and replaces the local results when done.
This commit is contained in:
2026-03-29 17:48:01 -04:00
parent c22066e5d5
commit c3e16a9fd2
3 changed files with 52 additions and 27 deletions
+24
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"log/slog"
"math"
"net/http"
"sort"
"strings"
"sync"
@@ -156,6 +157,29 @@ func (e *Service) SearchLocal(query string) *MBSearchResult {
return &result
}
// SearchLocalHandler returns an http.Handler that serves local
// index search results as JSON. This bypasses the Wails RPC
// serialization queue, ensuring sub-millisecond response times.
func (e *Service) SearchLocalHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
if query == "" {
w.WriteHeader(http.StatusBadRequest)
return
}
result := e.SearchLocal(query)
if result == nil {
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte("null"))
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(result)
})
}
// ---------------------------------------------------------------------------
// MusicBrainz lookup
// ---------------------------------------------------------------------------