feat: autotag mixed-bag splitting, search relevance fixes, and multi-library download imports
Autotag: detect "junk drawer" folders with no artist/album consensus and split them into synthetic per-cluster groups instead of forcing one match on an unrelated pile of tracks; repair tagging_items rows left behind by a prior scan orphan-cleanup gap. Explore: fix an exact artist-name search being drowned out by its own catalog entries in intent-prior scoring, and prune stale in_library bookkeeping left behind when a referenced library row is deleted. Download: fix a multi-library regression where every import failed with "no library root configured" — the importer resolved the library root from a legacy single-library config field that nothing populates in the current multi-library model. It now resolves the destination library per-request from the request's own library_id. Also widen the Soulseek search window (12s -> 20s), measured against real request history to be missing available peers on live queries. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2Agd9af5hE7qzti2ackiS
This commit is contained in:
+41
-1
@@ -61,6 +61,18 @@ type MBClient interface {
|
||||
query string,
|
||||
limit int,
|
||||
) ([]MBReleaseGroupHit, int, error)
|
||||
// SearchReleaseGroupsLocal searches the offline dump-derived
|
||||
// catalog for release groups matching albumName — no network
|
||||
// round-trip. ok is false when the local catalog isn't
|
||||
// populated yet (or the implementation has no offline index),
|
||||
// telling the caller to rely on the network cascade alone; ok
|
||||
// true with zero hits means the catalog was consulted and
|
||||
// genuinely has nothing.
|
||||
SearchReleaseGroupsLocal(
|
||||
ctx context.Context,
|
||||
albumName string,
|
||||
limit int,
|
||||
) (hits []MBReleaseGroupHit, ok bool)
|
||||
SearchRecordings(
|
||||
ctx context.Context,
|
||||
query string,
|
||||
@@ -128,12 +140,40 @@ func (r *MBResolver) ResolveMB(ctx context.Context, g Group) ([]Candidate, error
|
||||
}
|
||||
|
||||
nArtist := Normalize(groupArtist(g))
|
||||
steps := buildMBQueryCascade(nAlbum, nArtist, len(g.Tracks), vaLikely(g))
|
||||
|
||||
seen := make(map[string]bool)
|
||||
|
||||
var merged []Candidate
|
||||
|
||||
// Local-index pass: the offline dump-derived catalog covers
|
||||
// essentially every popular release group, so try it before
|
||||
// spending any rate-limited search calls. This never skips
|
||||
// BrowseReleases (the catalog doesn't carry per-release
|
||||
// tracklists) but it very often means the network Lucene
|
||||
// cascade below never has to run at all.
|
||||
if localHits, ok := r.client.SearchReleaseGroupsLocal(ctx, g.AlbumName, r.limit); ok {
|
||||
added := r.fanOutBrowse(ctx, g, localHits, "index", seen, &merged)
|
||||
|
||||
r.logger.Debug(
|
||||
"local index search done",
|
||||
"hits", len(localHits), "new_candidates", added,
|
||||
)
|
||||
|
||||
if added > 0 {
|
||||
ranked := RankCandidates(g, merged)
|
||||
if len(ranked) > 0 && ranked[0].Score >= cascadeSufficient {
|
||||
r.logger.Info(
|
||||
"MB cascade stopped — sufficient local-index candidate",
|
||||
"score", ranked[0].Score,
|
||||
)
|
||||
|
||||
return merged, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
steps := buildMBQueryCascade(nAlbum, nArtist, len(g.Tracks), vaLikely(g))
|
||||
|
||||
for _, step := range steps {
|
||||
hits, _, err := r.client.SearchReleaseGroups(ctx, step.query, r.limit)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user