fix(orbit): cleanup regex, state-blob budget, radio top-up lockout (#1155)

* fix(orbit): stop cleanup sweep from deleting live sessions on other devices

The orphan-cleanup regex anchored the trailing `__` inside the optional
`_from_…` group, so the canonical session playlist name
(`__psyorbit_<sid>__`) never matched. It then fell into the
"unrecognised → prune" branch, which deletes unconditionally and bypasses
the orphan-TTL grace that exists precisely to protect a session running on
the user's other device. Opening Psysonic on a second device wiped the
first device's live session out from under its guests.

Move the trailing `__` outside the optional group so both the session and
outbox names match; the existing sid/TTL/ended logic then applies as
intended. Add a behavioural test covering keep-fresh / prune-stale /
prune-ended / skip-current / outbox / corrupt / foreign-owner cases.

* fix(orbit): keep host publishing when the state blob grows past budget

OrbitState.queue (the suggestion/attribution history) was append-only at
the sweep-fold step and never bounded. On a long session it grew until the
serialised blob exceeded ORBIT_STATE_MAX_BYTES; serialiseOrbitState then
threw, writeOrbitState's caller swallowed the error and retried the same
over-budget state every tick, so the host silently stopped publishing and
guests froze into a host-timeout.

Two layers:
- Cap queue at ORBIT_QUEUE_HISTORY_LIMIT in applyOutboxSnapshotsToState,
  evicting oldest-by-addedAt (robust to the periodic queue shuffle). The
  dropped tracks have long since played, so their attribution/dedupe entry
  is dead weight.
- Add serialiseOrbitStateForWire: a budget-aware serialiser that sheds
  oldest history, then the play-queue tail, on a copy before giving up.
  writeOrbitState now uses it, so a transient over-budget tick degrades the
  published blob instead of taking the host offline. Local store state is
  untouched.

Tested: history cap eviction order, wire-trim byte budget + oldest-first
drop, play-queue fallback, and within-budget passthrough.

* fix(orbit): lock out the proactive radio top-up during a session

The ≤2-remaining radio top-up in runNext lacked the isInOrbitSession()
guard that its infinite-queue sibling has at both entry and resolution.
A guest who joined with residual radioAdded tracks (before the first
syncToHost replaces the queue) could fire it, appending up to 10 unrelated
radio tracks and trimming queue history — drifting the guest off the host's
playlist.

Add the guard at entry and re-check inside the resolution .then(), mirroring
the infinite-queue branch; the existing finally() still clears the fetching
flag. The queue-exhausted radio fallback already returns early in Orbit, so
only this mid-queue path was unguarded.

* docs(changelog): add Orbit cleanup / state-budget / radio fixes (#1155)

* docs(changelog): move Orbit fixes to bottom of Fixed section (#1155)
This commit is contained in:
Psychotoxical
2026-06-22 13:33:09 +02:00
committed by GitHub
parent bd43ea5240
commit 2c9b2eeb46
11 changed files with 475 additions and 7 deletions
+18
View File
@@ -206,6 +206,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* **Favorites** on All Albums uses the same `getStarred2` catalog path as the Favorites page instead of the empty sparse `album` table browse.
* Pre-index compilation filtering auto-paginates again in network page mode; offline library aggregates set `isCompilation` from track tags.
### Orbit — opening the app on another device could end a live session
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1155](https://github.com/Psychotoxical/psysonic/pull/1155)**
* Starting Psysonic on a second device while you were hosting or in an Orbit session could delete that session's playlist, dropping your guests as if you had ended it. The start-up cleanup that clears leftover Orbit playlists now leaves a session that is still live on another device alone.
### Orbit — long sessions could quietly stop updating for guests
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1155](https://github.com/Psychotoxical/psysonic/pull/1155)**
* During a long Orbit session the host could silently stop broadcasting, leaving guests frozen until they timed out. The shared session data is now kept within its size limit (trimming the oldest suggestion history first), so the host keeps updating instead of stalling.
### Orbit — radio could add unrelated tracks for guests
**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1155](https://github.com/Psychotoxical/psysonic/pull/1155)**
* A guest who joined while radio was playing could have unrelated radio tracks appended to their queue, drifting them out of sync with the host. Automatic radio top-up is now paused while you are in an Orbit session.
## [1.48.1] - 2026-06-15
## Fixed