The server now sends each fresh position on every poll that has one, and sends positions advanced to send time; clients count only the time since they received it. Bars realign every poll and no longer drift by however far the viewer's clock is off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -3,7 +3,7 @@ import { afterEach, describe, expect, it } from 'vitest';
|
||||
import { db, schema } from '../src/db';
|
||||
import { createRedis, nowPlayingChannel } from '../src/lib/redis';
|
||||
import { reportedPosition } from '../src/routes/devices';
|
||||
import { applyPollResult } from '../src/services/nowPlaying';
|
||||
import { applyPollResult, getNowPlaying } from '../src/services/nowPlaying';
|
||||
import { nextPollDelay } from '../src/services/scheduler';
|
||||
import { createUser, useTestApp } from './helpers';
|
||||
|
||||
@@ -54,27 +54,44 @@ describe('phone-reported positions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('seeking', () => {
|
||||
it('tells watchers when the position jumps, but not as it ticks along', async () => {
|
||||
describe('realigning progress bars', () => {
|
||||
it('sends the fresh position on every poll that has one, advanced to send time', async () => {
|
||||
const { user } = await createUser(app(), 'alice');
|
||||
await applyPollResult(user.id, 'plex', playing(0));
|
||||
// Pretend the last poll was 10 seconds ago.
|
||||
await db
|
||||
.update(schema.nowPlaying)
|
||||
.set({ updatedAt: new Date(Date.now() - 10_000) })
|
||||
.where(eq(schema.nowPlaying.userId, user.id));
|
||||
|
||||
const messages: string[] = [];
|
||||
await sub.subscribe(nowPlayingChannel(user.id));
|
||||
sub.on('message', (_channel, msg) => messages.push(msg));
|
||||
|
||||
await applyPollResult(user.id, 'plex', playing(10_500)); // right where it should be
|
||||
await new Promise((r) => setTimeout(r, 150));
|
||||
expect(messages).toHaveLength(0);
|
||||
|
||||
await applyPollResult(user.id, 'plex', playing(10_500));
|
||||
await db
|
||||
.update(schema.nowPlaying)
|
||||
.set({ updatedAt: new Date(Date.now() - 3_000) }) // as if that poll was 3s ago
|
||||
.where(eq(schema.nowPlaying.userId, user.id));
|
||||
await applyPollResult(user.id, 'plex', playing(120_000)); // skipped ahead
|
||||
await new Promise((r) => setTimeout(r, 150));
|
||||
expect(messages).toHaveLength(1);
|
||||
expect(JSON.parse(messages[0]!)).toMatchObject({ progressMs: 120_000 });
|
||||
const sent = messages.map((m) => JSON.parse(m).progressMs as number);
|
||||
expect(sent).toHaveLength(2);
|
||||
expect(sent[0]).toBeGreaterThanOrEqual(10_500);
|
||||
expect(sent[0]).toBeLessThan(11_500);
|
||||
expect(sent[1]).toBeGreaterThanOrEqual(120_000);
|
||||
expect(sent[1]).toBeLessThan(121_000);
|
||||
|
||||
// Fetched later, the position has moved on by the time since the poll.
|
||||
const [np] = await getNowPlaying([user.id]);
|
||||
await db.update(schema.nowPlaying).set({ updatedAt: new Date(Date.now() - 4_000) }).where(eq(schema.nowPlaying.userId, user.id));
|
||||
const [later] = await getNowPlaying([user.id]);
|
||||
expect(np!.progressMs).toBeGreaterThanOrEqual(120_000);
|
||||
expect(later!.progressMs).toBeGreaterThanOrEqual(124_000);
|
||||
});
|
||||
|
||||
it("doesn't send anything extra for sources without a position", async () => {
|
||||
const { user } = await createUser(app(), 'alice');
|
||||
await applyPollResult(user.id, 'lastfm', playing(null));
|
||||
const messages: string[] = [];
|
||||
await sub.subscribe(nowPlayingChannel(user.id));
|
||||
sub.on('message', (_channel, msg) => messages.push(msg));
|
||||
await applyPollResult(user.id, 'lastfm', playing(null));
|
||||
await new Promise((r) => setTimeout(r, 150));
|
||||
expect(messages).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user