Skip to content

core: cache liked songs - #1

Merged
and2049 merged 6 commits into
mainfrom
liked-songs-cache
Sep 26, 2026
Merged

and2049 merged 6 commits into
mainfrom
liked-songs-cache

Conversation

@and2049

@and2049 and2049 commented Sep 26, 2026

Copy link
Copy Markdown
Owner

No description provided.

Spotify lists saved tracks newest first, so one page tells a head check
what was liked since the last sync, and the page's total tells it whether
anything was removed elsewhere. Only when the two disagree, on first use,
or as a weekly backstop does the library need a full walk.

The walk is resumable: it records how many items it has consumed and
starts over only when the total moves under it. The committed list stays
in use until a walk finishes with exactly Spotify's count. Local files
count toward the total but are not shown.

The list lives in its own file because cache.json is rewritten whole on
every cache update and should not carry thousands of rows.
The startup sync walked every saved-track page daily through rspotify's
stream, 100 ms apart, and kept only the ids. A failed page, a 429
included, was skipped and the partial set still replaced the hearts
until the next day's walk. Local-file likes were dropped by the same
replacement.

Pages now go through the client's rate-limit gate, so a 429 records
Spotify's Retry-After as a cooldown and stops the sync. On startup, one
page is usually enough: it picks up new likes and confirms nothing was
removed elsewhere. A walk runs only when that check fails, on first use
or weekly. It sends one request a second, saves its progress every ten
pages, resumes from there after a restart or cooldown, and replaces the
hearts only once it has read exactly Spotify's count. Local-file hearts
are kept.

Likes and unlikes made in echo update the stored list once Spotify
accepts them: an unlike drops the row without a request, a like marks
the head for the next check.
Opening Liked Songs fetched its first 100 rows again and asked Spotify
for the count in a separate request. It now shows the stored list and
count at once and leaves Spotify to the sync, which usually makes one
request at most and none if the last check was recent. An explicit
refresh forces the head check.

The open list updates in place, keeping selection and sort, when a head
check finds new likes, when a first walk has more rows to show, when a
walk finishes, and when a song is unliked in echo. If nothing is stored
yet and the sync fails, a rate-limit cooldown included, the status line
says why.

Playing Liked Songs from the top takes its first 100 ids from the stored
list instead of fetching them. The view's old 100-row entry in
cache.json is dropped after the first completed walk.
ksni's default "tokio" feature turns on zbus's tokio backend for the
whole build. GPUI's own zbus users (AccessKit, the XDG portals,
notify-rust) then call into zbus from threads outside any tokio runtime,
and zbus panics with "there is no reactor running" when it spawns a
blocking task.

With async-io, ksni and zbus drive D-Bus on their own executor and no
longer assume a tokio runtime.
@and2049
and2049 merged commit 0bbdfd4 into main Sep 26, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant