Retry indexer search with stripped parenthetical suffixes when initial query returns no results

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Alexander
2026-05-11 20:36:52 +02:00
parent 9aff4b0a29
commit 0fd51a1e03
2 changed files with 121 additions and 11 deletions
+46 -11
View File
@@ -588,23 +588,58 @@ func (service *MusicAgregatorService) searchIndexer(album *metadataPb.Album, tra
artistName = album.GetArtists()[0].GetArtist().GetName()
}
query := album.GetTitle()
if artistName != "" {
query = artistName + " " + query
}
if tracker == "" {
tracker = "all"
}
result, err := service.indexer.Search(query, -1, tracker)
if err != nil {
log.Error().Err(err).Str("query", query).Msg("indexer search failed")
return nil, err
title := album.GetTitle()
queries := buildSearchQueries(artistName, title)
for _, query := range queries {
result, err := service.indexer.Search(query, -1, tracker)
if err != nil {
log.Error().Err(err).Str("query", query).Msg("indexer search failed")
return nil, err
}
log.Debug().Int("results", len(result.Items)).Str("query", query).Msg("indexer search completed")
if len(result.Items) > 0 {
return result, nil
}
log.Debug().Str("query", query).Msg("no results, trying broader search")
}
log.Debug().Int("results", len(result.Items)).Str("query", query).Msg("indexer search completed")
return result, nil
return &indexer.SearchResponse{}, nil
}
func buildSearchQueries(artist, title string) []string {
base := title
if artist != "" {
base = artist + " " + title
}
queries := []string{base}
stripped := stripParenthetical(title)
if stripped != title {
q := stripped
if artist != "" {
q = artist + " " + stripped
}
queries = append(queries, q)
}
return queries
}
func stripParenthetical(s string) string {
idx := strings.Index(s, "(")
if idx > 0 {
return strings.TrimSpace(s[:idx])
}
return s
}
func (service *MusicAgregatorService) parseSearchResults(searchResult *indexer.SearchResponse, album *metadataPb.Album) []parsedItem {
+75
View File
@@ -1131,3 +1131,78 @@ func TestRecoverOrphaned_FindsActiveDownloads(t *testing.T) {
assert.Equal(t, "orphan-hash", active[0].QbitHash)
assert.Equal(t, "downloading", active[0].State)
}
func TestMonitorAlbum_SearchRetryAllExhausted(t *testing.T) {
suite := setupSuite(t)
cleanTables(t, suite.pool)
suite.mocks.metadata.GetAlbumFunc = func(ctx context.Context, in *metadataPb.GetAlbumRequest, opts ...grpc.CallOption) (*metadataPb.GetAlbumResponse, error) {
return &metadataPb.GetAlbumResponse{
Album: newMetadataAlbum("test-album-ext-id", "Ain't My Bitch (remastered)", "artist-ext-id", "Metallica"),
}, nil
}
var queryCount int
suite.mocks.indexer.SearchFunc = func(query string, limit int32, idx string) (*indexer.SearchResponse, error) {
queryCount++
return newSearchResponse(), nil
}
ctx := context.Background()
resp, err := suite.client.MonitorAlbum(ctx, &pb.MonitorAlbumRequest{
AlbumId: "test-album-ext-id",
Quality: pb.QualityType_QUALITY_LOSSLESS,
})
require.NoError(t, err)
require.NotNil(t, resp.Album)
assert.Nil(t, resp.Release)
assert.Equal(t, 2, queryCount)
}
func TestMonitorAlbum_SearchRetryWithStrippedTitle(t *testing.T) {
suite := setupSuite(t)
cleanTables(t, suite.pool)
suite.mocks.metadata.GetAlbumFunc = func(ctx context.Context, in *metadataPb.GetAlbumRequest, opts ...grpc.CallOption) (*metadataPb.GetAlbumResponse, error) {
return &metadataPb.GetAlbumResponse{
Album: newMetadataAlbum("test-album-ext-id", "Ain't My Bitch (remastered)", "artist-ext-id", "Metallica"),
}, nil
}
var queries []string
suite.mocks.indexer.SearchFunc = func(query string, limit int32, idx string) (*indexer.SearchResponse, error) {
queries = append(queries, query)
if len(queries) == 1 {
return newSearchResponse(), nil
}
return newSearchResponse(
newSearchItem("Metallica - Load [FLAC]", 50, "magnet:?xt=urn:btih:abc123"),
), nil
}
suite.mocks.magnet.ResolveFunc = func(magnetURI string) ([]byte, error) {
return newTorrentData(), nil
}
suite.mocks.torrent.FindFunc = func(opts torrent.FindOptions) ([]torrent.TorrentInfo, error) {
return []torrent.TorrentInfo{}, nil
}
suite.mocks.torrent.AddMagnetFunc = func(magnetURI string, savePath string) error {
return nil
}
ctx := context.Background()
resp, err := suite.client.MonitorAlbum(ctx, &pb.MonitorAlbumRequest{
AlbumId: "test-album-ext-id",
Quality: pb.QualityType_QUALITY_LOSSLESS,
})
require.NoError(t, err)
require.NotNil(t, resp.Release)
require.Len(t, queries, 2)
assert.Equal(t, "Metallica Ain't My Bitch (remastered)", queries[0])
assert.Equal(t, "Metallica Ain't My Bitch", queries[1])
}