fix: add panic recovery to search-local handler, remove unused event emission
Added defer/recover to SearchLocalHandler to prevent panics from crashing the app. Removed the now-unused Wails event emission from Search() and the runtime import — local results are served via the HTTP endpoint exclusively.
This commit is contained in:
+15
-42
@@ -11,8 +11,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
|
||||||
|
|
||||||
"yellowjacket/backend/database"
|
"yellowjacket/backend/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -162,20 +160,29 @@ func (e *Service) SearchLocal(query string) *MBSearchResult {
|
|||||||
// serialization queue, ensuring sub-millisecond response times.
|
// serialization queue, ensuring sub-millisecond response times.
|
||||||
func (e *Service) SearchLocalHandler() http.Handler {
|
func (e *Service) SearchLocalHandler() http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer func() {
|
||||||
|
if rv := recover(); rv != nil {
|
||||||
|
e.logger.Error("search-local handler panic", "recover", rv)
|
||||||
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
query := r.URL.Query().Get("q")
|
query := r.URL.Query().Get("q")
|
||||||
if query == "" {
|
if query == "" {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
result := e.SearchLocal(query)
|
|
||||||
if result == nil {
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, _ = w.Write([]byte("null"))
|
_, _ = w.Write([]byte("null"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result := e.SearchLocal(query)
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
if result == nil {
|
||||||
|
_, _ = w.Write([]byte("null"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_ = json.NewEncoder(w).Encode(result)
|
_ = json.NewEncoder(w).Encode(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -363,40 +370,6 @@ func (e *Service) Search(query string) (*MBSearchResult, error) {
|
|||||||
"elapsed", p0Dur.Round(time.Millisecond),
|
"elapsed", p0Dur.Round(time.Millisecond),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Emit local results immediately via event so the frontend can
|
|
||||||
// render them while the full pipeline runs. This avoids the
|
|
||||||
// Wails RPC serialization bottleneck that blocks SearchLocal.
|
|
||||||
if len(indexHits) > 0 {
|
|
||||||
var localResult MBSearchResult
|
|
||||||
mergeIndexHits(&localResult, indexHits)
|
|
||||||
|
|
||||||
// Remove SPAs from local results.
|
|
||||||
if len(localResult.Artists) > 0 {
|
|
||||||
filtered := localResult.Artists[:0]
|
|
||||||
for _, a := range localResult.Artists {
|
|
||||||
if !mbSpecialPurposeArtists[a.MBID] {
|
|
||||||
filtered = append(filtered, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
localResult.Artists = filtered
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(localResult.Artists) > maxResults {
|
|
||||||
localResult.Artists = localResult.Artists[:maxResults]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(localResult.ReleaseGroups) > maxResults {
|
|
||||||
localResult.ReleaseGroups = localResult.ReleaseGroups[:maxResults]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(localResult.Recordings) > maxResults {
|
|
||||||
localResult.Recordings = localResult.Recordings[:maxResults]
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime.EventsEmit(e.ctx, "search:local-results", localResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 1: concurrent MB search (3 goroutines) with a deadline
|
// Phase 1: concurrent MB search (3 goroutines) with a deadline
|
||||||
// so a slow MusicBrainz server doesn't hold up the whole search.
|
// so a slow MusicBrainz server doesn't hold up the whole search.
|
||||||
p1Start := time.Now()
|
p1Start := time.Now()
|
||||||
|
|||||||
+3
@@ -1,6 +1,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
import {explore} from '../models';
|
import {explore} from '../models';
|
||||||
|
import {http} from '../models';
|
||||||
import {context} from '../models';
|
import {context} from '../models';
|
||||||
|
|
||||||
export function BrowseReleaseGroups(arg1:string):Promise<Array<explore.MBReleaseGroup>>;
|
export function BrowseReleaseGroups(arg1:string):Promise<Array<explore.MBReleaseGroup>>;
|
||||||
@@ -37,6 +38,8 @@ export function SearchArtists(arg1:string):Promise<Array<explore.MBArtist>>;
|
|||||||
|
|
||||||
export function SearchLocal(arg1:string):Promise<explore.MBSearchResult>;
|
export function SearchLocal(arg1:string):Promise<explore.MBSearchResult>;
|
||||||
|
|
||||||
|
export function SearchLocalHandler():Promise<http.Handler>;
|
||||||
|
|
||||||
export function SearchRecordings(arg1:string):Promise<Array<explore.MBRecording>>;
|
export function SearchRecordings(arg1:string):Promise<Array<explore.MBRecording>>;
|
||||||
|
|
||||||
export function SearchReleaseGroups(arg1:string):Promise<Array<explore.MBReleaseGroup>>;
|
export function SearchReleaseGroups(arg1:string):Promise<Array<explore.MBReleaseGroup>>;
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ export function SearchLocal(arg1) {
|
|||||||
return window['go']['explore']['Service']['SearchLocal'](arg1);
|
return window['go']['explore']['Service']['SearchLocal'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SearchLocalHandler() {
|
||||||
|
return window['go']['explore']['Service']['SearchLocalHandler']();
|
||||||
|
}
|
||||||
|
|
||||||
export function SearchRecordings(arg1) {
|
export function SearchRecordings(arg1) {
|
||||||
return window['go']['explore']['Service']['SearchRecordings'](arg1);
|
return window['go']['explore']['Service']['SearchRecordings'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user