Watch party refresh: Chat/Queue/Room tabs, host transport, gentle sync, heartbeat and latency-aware reconnect, in-place section updates
This commit is contained in:
@@ -134,7 +134,9 @@ export function createPartyHub({ now = () => Date.now() } = {}) {
|
||||
if (me.tokens < 1) return; // flood: drop
|
||||
me.tokens -= 1;
|
||||
}
|
||||
if (m.type === 'direct') {
|
||||
if (m.type === 'ping') {
|
||||
send(ws, { type: 'pong', echo: Number(m.echo) || 0, now: now() });
|
||||
} else if (m.type === 'direct') {
|
||||
p.direct.handle(me.pid, m, new Map([...p.members].map(([pid, member]) => [pid, member.ws])), send);
|
||||
} else if (m.type === 'dj') {
|
||||
if (m.action === 'take' && isHost) { const video = takeDJVideo(p.dj); send(ws, { type: 'dj-play', video }); if (video) broadcast(p, { type: 'dj', ...queueSnapshot(p.dj) }); }
|
||||
|
||||
@@ -187,3 +187,18 @@ describe('watch party seat rules', () => {
|
||||
host.send({ type: 'end' }); await host.closed;
|
||||
});
|
||||
});
|
||||
|
||||
test('heartbeat replies only to the sender with the server clock', async () => {
|
||||
const h = client({ role: 'host', pid: 'heartbeat-host', name: 'Host' });
|
||||
const hello = await h.next('hello');
|
||||
const g = client({ role: 'guest', pid: 'heartbeat-guest', code: hello.code, name: 'Guest' });
|
||||
await g.next('hello');
|
||||
const before = Date.now();
|
||||
g.send({ type: 'ping', echo: 12345 });
|
||||
const pong = await g.next('pong');
|
||||
expect(pong.echo).toBe(12345);
|
||||
expect(pong.now).toBeGreaterThanOrEqual(before);
|
||||
expect(pong.now).toBeLessThanOrEqual(Date.now());
|
||||
await expect(h.next('pong', 50)).rejects.toThrow('timeout pong');
|
||||
g.ws.close(); h.send({ type: 'end' }); await h.closed;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user