mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-21 22:15:40 +00:00
fix(orbit): tear down session on server switch + raise cleanup TTL
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+6
-6
@@ -732,13 +732,13 @@ export async function sweepGuestOutboxes(sid: string, hostUsername: string): Pro
|
||||
export const ORBIT_HEARTBEAT_ALIVE_MS = 30_000;
|
||||
|
||||
/**
|
||||
* Grace window for the app-start orphan sweep. Has to be comfortably
|
||||
* larger than the outbox heartbeat interval (10 s) and the session state
|
||||
* tick (2.5 s) so a session running on the user's other device doesn't
|
||||
* get deleted on a transient slow tick. 2× ALIVE window is the minimum
|
||||
* sane value.
|
||||
* Grace window for the app-start orphan sweep. A session on the user's
|
||||
* other device or a browser that briefly restarted must NOT be deleted
|
||||
* by this sweep. 5 min matches the guest-side host-timeout threshold:
|
||||
* if a session is silent for that long, it's fair to treat it as dead;
|
||||
* anything shorter is a real restart and must survive.
|
||||
*/
|
||||
export const ORBIT_ORPHAN_TTL_MS = 60_000;
|
||||
export const ORBIT_ORPHAN_TTL_MS = 5 * 60_000;
|
||||
|
||||
/**
|
||||
* Legacy / fallback shuffle cadence. New sessions store their own interval
|
||||
|
||||
@@ -1,11 +1,31 @@
|
||||
import { pingWithCredentials, scheduleInstantMixProbeForServer } from '../api/subsonic';
|
||||
import type { ServerProfile } from '../store/authStore';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { useOrbitStore } from '../store/orbitStore';
|
||||
import { endOrbitSession, leaveOrbitSession } from './orbit';
|
||||
|
||||
export async function switchActiveServer(server: ServerProfile): Promise<boolean> {
|
||||
try {
|
||||
const ping = await pingWithCredentials(server.url, server.username, server.password);
|
||||
if (!ping.ok) return false;
|
||||
|
||||
// Tear down any active Orbit session before we actually switch. The
|
||||
// session's playlists live on the *old* server — once we flip the
|
||||
// active server, every API call from the orbit hooks would hit the
|
||||
// wrong backend, heartbeats would silently fail, and the next
|
||||
// app-start cleanup would prune the still-live session as stale.
|
||||
// Capped at 1.5 s so a slow network doesn't freeze the UI.
|
||||
const role = useOrbitStore.getState().role;
|
||||
if (role === 'host' || role === 'guest') {
|
||||
const teardown = role === 'host' ? endOrbitSession() : leaveOrbitSession();
|
||||
await Promise.race([
|
||||
teardown.catch(() => {}),
|
||||
new Promise<void>(r => setTimeout(r, 1500)),
|
||||
]);
|
||||
// Ensure local store is idle even if the remote call timed out.
|
||||
useOrbitStore.getState().reset();
|
||||
}
|
||||
|
||||
const identity = {
|
||||
type: ping.type,
|
||||
serverVersion: ping.serverVersion,
|
||||
|
||||
Reference in New Issue
Block a user