github Nezreka/SoulSync 3.2.4
Version 3.2.4

3 hours ago

soulsync 3.2.4: devmain

a fix release. indexers stop getting hammered, cover art stops costing a file its tags, and the auto sync page stops claiming playlists never ran when they had.

soulseek was paced, prowlarr never was

everything in soulsync that talks to somebody else's server is paced. thirteen metadata services each hold their own minimum interval, slskd search creation goes through one shared budget. prowlarr had nothing at all, on either side, and it hands every search straight to your indexers.

the video wishlist drain is the one that hurt. three items at a time, each fanning out two or three search strategies at once, and the next item starting the moment one finished. that is a search landing on every indexer you have every couple of seconds for as long as the wishlist is long. reported as indexers getting upset, and the download history showed it plainly: one item searched, another one under five seconds later.

there is a shared budget now, same shape as the slskd one, used by the music and video sides together since it is one prowlarr in front of one set of indexers. two seconds apart, twenty a minute, both configurable, zero disables either half. a 429 from prowlarr puts everyone on a shared cooldown instead of the other half of the app walking into the same wall a second later.

one slot per search wave, not per request: a per indexer fan out gives each indexer exactly one query, so billing it per request would have added twenty seconds to an album search somebody is waiting on. manual video searches give up after twelve seconds and say so rather than holding a page open while a drain empties the window.

RSS is deliberately untouched and its interval stays at 15 minutes. it is one aggregate call per tick that searches nothing, so the interval barely moves indexer load at all, which is why moving it from 15 to 60 didn't help.

oversized cover art no longer costs the file its tags

a FLAC metadata block carries its length in 24 bits, so nothing over about 16MB can ever be written. nothing checked, the art went straight in, and mutagen only finds out at save time. so the log said "album art successfully embedded" and then the whole tag write died: the track ended up with no art AND no tags.

it is reachable on ordinary downloads, because soulsync deliberately prefers a CDN's original over the smaller thumbnail and some of those are big.

oversized art gets re-encoded to fit now, quality first and then dimensions, since a 4000px cover at quality 85 is usually already under the limit. if it can't be re-encoded at all the tags still get written without art, which beats losing both.

the atomic save was also catching that error and then running the same impossible write directly against your real file. that is why the log carried the same traceback twice. a tagging error means the tags cannot be encoded at all, so retrying cannot help, and the function already applies exactly that reasoning to its own integrity check.

the enhanced artist view was hiding releases

two things, both from the react port copying the old page a bit too faithfully.

the stats bar and the sections underneath it classified releases separately, so a release typed "EP" rendered under EPs and counted as none of the three numbers directly above it. the number and the list under it could disagree, which is a good way to make a page look broken. one classifier now, used by both.

worse, the view only ever drew albums, EPs and singles. anything else was loaded, sorted into a bucket, and then never rendered. compilations are the usual victim, so a greatest hits release in your library was invisible on that page. every type gets a section now.

worth knowing, because it explains a number that still looks off: a release with no type recorded counts as an album. nothing fills that field during a media server scan, only the enrichment workers do, so an unenriched library reads high. running enrichment on the artist fills it in.

"no runs yet" on a playlist that had just run

reported with the best possible evidence, two runs back to back in the log where one worked and one didn't.

the sync step skips when the track list hasn't changed and everything already matched. that is right as work, there is nothing to download. but it skipped the BOOKKEEPING with it, so nothing recorded that the run happened at all: the dashboard card had no run to show, said "no runs yet", and since the row keys its click handler on a run it stopped opening too. always the same playlists, because those are the ones whose contents had not moved.

a no-op sync writes a finished run now, because that is what it is. every track present, none downloaded, none failed.

the same card was also losing playlists a second way: it asked for the ten most recent syncs and then threw the album downloads away in javascript, so five recent album downloads left five playlist runs for eight scheduled playlists to match against. a filter after LIMIT is not a filter. it is a server side condition now, and a row opens its playlist whether or not it has a recent run.

publish order, and a suite you can believe, thanks @nick2000713

albums published in whatever order the filesystem handed the files back, so the same album published track 1 first on one machine and track 2 first on another. that decides which files are already live when a later one fails, which decides what the rollback has to undo. sorted now, and by track NUMBER rather than by its spelling, so a 100 track boxset doesn't sort 100 in among the ones.

it had also quietly disarmed the guard for the db pointer rollback that shipped in 3.2.3: on a machine that walks the second file first, the failing track is the first one, nothing has published, and the rollback never runs. the test passed with the fix deleted. that is a good catch and it was found by noticing its sibling go red.

the video database could also fail to come up if two things opened it at the same moment, a restart racing a running worker: both see a column missing, both add it, the loser dies and takes the whole database init with it. only the duplicate is swallowed now, anything else is still a real failure.

plus eighteen test failures that were tests standing on each other's shared state rather than real bugs, and four lint errors that were blocking CI.

quality profile settings save where you can see them, thanks @nick2000713

the quality page made it look like settings saved, but the pencil on the profile row was the real save path. change quality on import, hit save, switch profiles and come back, and you saw the old values.

the profile you are looking at is the save target now, and the page's own Save Settings button saves it too. the delayed save captures which profile and what values before it fires, so switching profiles quickly can't write your edit into the wrong one.

Don't miss a new SoulSync release

NewReleases is sending notifications on new releases.