lbry-desktop/web/src/livestreaming/long-polling.js
2021-11-15 12:34:21 -06:00

70 lines
1.9 KiB
JavaScript

// @flow
/*
* This module is responsible for long polling the server to determine if a channel is actively streaming.
*
* One or many entities can subscribe to the live status while instantiating just one long poll interval per channel.
* Once all interested parties have disconnected the poll will shut down. For this reason, be sure to always call the
* disconnect function returned upon connecting.
*/
import { isLiveStreaming } from '$web/src/livestreaming';
const POLL_INTERVAL = 30000; // 30 seconds.
const pollers = {};
const pollingMechanism = {
streaming: false,
startPolling() {
if (this.interval !== 0) return;
const poll = async () => {
this.streaming = await isLiveStreaming(this.channelId);
this.subscribers.forEach((cb) => {
if (cb) cb(this.streaming);
});
};
poll();
this.interval = setInterval(poll, POLL_INTERVAL);
},
stopPolling() {
clearInterval(this.interval);
this.interval = 0;
},
connect(cb): number {
cb(this.streaming);
this.startPolling();
return this.subscribers.push(cb) - 1;
},
disconnect(subscriberIndex: number) {
this.subscribers[subscriberIndex] = null;
if (this.subscribers.every((item) => item === null)) {
this.stopPolling();
delete pollers[this.channelId];
}
},
};
const generateLongPoll = (channelId: string) => {
if (pollers[channelId]) return pollers[channelId];
pollers[channelId] = Object.create({
channelId,
interval: 0,
subscribers: [],
...pollingMechanism,
});
return pollers[channelId];
};
const watchLivestreamStatus = (channelId: ?string, cb: (boolean) => void) => {
if (!channelId || typeof cb !== 'function') return undefined;
const poll = generateLongPoll(channelId);
const subscriberIndex = poll.connect(cb);
return () => poll.disconnect(subscriberIndex);
};
export default watchLivestreamStatus;