mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-30 18:31:35 +03:00
Speed up /search
subsonic endpoints by parallelizing the queries
This commit is contained in:
parent
d613b19306
commit
cd5bce7b16
@ -1,9 +1,13 @@
|
|||||||
package subsonic
|
package subsonic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kennygrant/sanitize"
|
"github.com/kennygrant/sanitize"
|
||||||
"github.com/navidrome/navidrome/log"
|
"github.com/navidrome/navidrome/log"
|
||||||
@ -46,25 +50,43 @@ func (c *SearchingController) getParams(r *http.Request) (*searchParams, error)
|
|||||||
return sp, nil
|
return sp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SearchingController) searchAll(r *http.Request, sp *searchParams) (model.MediaFiles, model.Albums, model.Artists) {
|
type searchFunc[T any] func(q string, offset int, size int) (T, error)
|
||||||
|
|
||||||
|
func doSearch[T any](ctx context.Context, wg *sync.WaitGroup, s searchFunc[T], q string, offset, size int) T {
|
||||||
|
defer wg.Done()
|
||||||
|
var res T
|
||||||
|
if size == 0 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
var err error
|
||||||
|
res, err = s(q, offset, size)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(ctx, "Error searching "+reflect.TypeOf(res).String(), err)
|
||||||
|
}
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
case <-ctx.Done():
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SearchingController) searchAll(r *http.Request, sp *searchParams) (mediaFiles model.MediaFiles, albums model.Albums, artists model.Artists) {
|
||||||
|
start := time.Now()
|
||||||
q := sanitize.Accents(strings.ToLower(strings.TrimSuffix(sp.query, "*")))
|
q := sanitize.Accents(strings.ToLower(strings.TrimSuffix(sp.query, "*")))
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
artists, err := c.ds.Artist(ctx).Search(q, sp.artistOffset, sp.artistCount)
|
wg.Add(3)
|
||||||
if err != nil {
|
go func() { mediaFiles = doSearch(ctx, wg, c.ds.MediaFile(ctx).Search, q, sp.songOffset, sp.songCount) }()
|
||||||
log.Error(ctx, "Error searching for Artists", err)
|
go func() { albums = doSearch(ctx, wg, c.ds.Album(ctx).Search, q, sp.albumOffset, sp.albumCount) }()
|
||||||
}
|
go func() { artists = doSearch(ctx, wg, c.ds.Artist(ctx).Search, q, sp.artistOffset, sp.artistCount) }()
|
||||||
albums, err := c.ds.Album(ctx).Search(q, sp.albumOffset, sp.albumCount)
|
wg.Wait()
|
||||||
if err != nil {
|
|
||||||
log.Error(ctx, "Error searching for Albums", err)
|
|
||||||
}
|
|
||||||
mediaFiles, err := c.ds.MediaFile(ctx).Search(q, sp.songOffset, sp.songCount)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(ctx, "Error searching for MediaFiles", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug(ctx, fmt.Sprintf("Search resulted in %d songs, %d albums and %d artists",
|
log.Debug(ctx, fmt.Sprintf("Search resulted in %d songs, %d albums and %d artists",
|
||||||
len(mediaFiles), len(albums), len(artists)), "query", sp.query)
|
len(mediaFiles), len(albums), len(artists)), "query", sp.query, "elapsedTime", time.Since(start))
|
||||||
return mediaFiles, albums, artists
|
return mediaFiles, albums, artists
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user