From 2b1124d14af16d4bc22bea91af0592aa63d8812d Mon Sep 17 00:00:00 2001 From: Psychotoxical <171614930+Psychotoxical@users.noreply.github.com> Date: Sat, 25 Apr 2026 00:10:40 +0200 Subject: [PATCH] fix(orbit): dedupe guest outbox entries per host sweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guest outboxes are append-only from the host's POV — every sweep reads the same playlist. `applyOutboxSnapshotsToState` was unconditionally pushing every trackId in every snapshot into `state.queue`, so the pending-approval list grew by one duplicate per tick for every unhandled suggestion (visible as 4+ identical rows after ~10 s). Dedupe against `(user, trackId)` already present in `state.queue` or `state.currentTrack` before appending. A guest re-suggesting the same track after it lands/plays is a rare enough case to live with for now. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/utils/orbit.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/utils/orbit.ts b/src/utils/orbit.ts index 68d8be37..39f39253 100644 --- a/src/utils/orbit.ts +++ b/src/utils/orbit.ts @@ -870,9 +870,24 @@ export function applyOutboxSnapshotsToState( nowMs: number = Date.now(), ): OrbitState { // ── Queue additions ── + // Guest outboxes are append-only from the host's POV — the host reads the + // same playlist every sweep, so we must dedupe against anything already in + // `state.queue` (or currently playing) by (user, trackId). Without this, + // every host tick re-adds every outbox entry and the pending-approval list + // balloons indefinitely. A user re-suggesting the same track after it + // lands/plays is a rare enough case to live with for now. + const existingKeys = new Set( + state.queue.map(q => `${q.addedBy}${q.trackId}`), + ); + if (state.currentTrack) { + existingKeys.add(`${state.currentTrack.addedBy}${state.currentTrack.trackId}`); + } const newItems: OrbitQueueItem[] = []; for (const snap of snapshots) { for (const trackId of snap.trackIds) { + const key = `${snap.user}${trackId}`; + if (existingKeys.has(key)) continue; + existingKeys.add(key); newItems.push({ trackId, addedBy: snap.user, addedAt: nowMs }); } }