polyv-live-cli
Version:
CLI tool for managing PolyV live streaming services.
228 lines • 7.52 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataManager = void 0;
const events_1 = require("events");
class DataManager extends events_1.EventEmitter {
constructor(streamService, channelService, config) {
super();
this.isRunning = false;
this.streamService = streamService;
this._channelService = channelService;
this.config = config;
this.channelCache = new Map();
this.lastCollectionTime = new Date(0);
this.setMaxListeners(50);
}
start() {
if (this.isRunning)
return;
this.isRunning = true;
this.scheduleNextCollection();
this.emit('dataManager:started', {
timestamp: new Date(),
config: this.config
});
}
stop() {
if (!this.isRunning)
return;
this.isRunning = false;
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
this.refreshTimer = undefined;
}
this.emit('dataManager:stopped', {
timestamp: new Date()
});
}
addChannel(channelId) {
if (!this.config.channels.includes(channelId)) {
this.config.channels.push(channelId);
this.channelCache.set(channelId, {
channelId,
lastUpdate: new Date(0),
retryCount: 0
});
this.emit('dataManager:channelAdded', {
channelId,
timestamp: new Date()
});
if (this.isRunning) {
this.collectChannelData(channelId);
}
}
}
removeChannel(channelId) {
const index = this.config.channels.indexOf(channelId);
if (index !== -1) {
this.config.channels.splice(index, 1);
this.channelCache.delete(channelId);
this.emit('dataManager:channelRemoved', {
channelId,
timestamp: new Date()
});
}
}
getChannelData(channelId) {
const entry = this.channelCache.get(channelId);
return entry?.metrics || null;
}
getAllChannelsData() {
const results = [];
for (const entry of this.channelCache.values()) {
if (entry.metrics) {
results.push(entry.metrics);
}
}
return results;
}
async collectData() {
const startTime = Date.now();
const timestamp = new Date();
try {
const metrics = [];
const errors = [];
const promises = this.config.channels.map(channelId => this.collectChannelData(channelId).catch(error => {
errors.push(error);
return null;
}));
const results = await Promise.all(promises);
for (const result of results) {
if (result) {
metrics.push(result);
}
}
this.lastCollectionTime = timestamp;
const duration = Date.now() - startTime;
const collectionResult = {
success: errors.length === 0,
data: metrics,
error: errors.length > 0 ? errors[0] : undefined,
timestamp,
duration
};
this.emit('dataManager:dataCollected', {
...collectionResult,
channelCount: this.config.channels.length,
successCount: metrics.length,
errorCount: errors.length
});
return collectionResult;
}
catch (error) {
const duration = Date.now() - startTime;
const collectionResult = {
success: false,
error: error instanceof Error ? error : new Error('Unknown collection error'),
timestamp,
duration
};
this.emit('dataManager:dataCollected', collectionResult);
return collectionResult;
}
}
async collectChannelData(channelId) {
const entry = this.channelCache.get(channelId) || {
channelId,
lastUpdate: new Date(0),
retryCount: 0
};
try {
const streamStatus = await this.streamService.getStreamStatus({ channelId });
const metrics = {
channelId,
bitrate: streamStatus.metrics?.bandwidth ? Math.round(streamStatus.metrics.bandwidth / 1000) : 0,
fps: streamStatus.metrics?.fps || 0,
resolution: '1920x1080',
viewerCount: 0,
status: streamStatus.isLive ? 'live' : 'offline',
uptime: streamStatus.duration || 0,
bandwidth: streamStatus.metrics?.bandwidth || 0,
lastUpdate: new Date()
};
entry.metrics = metrics;
entry.lastUpdate = new Date();
entry.error = undefined;
entry.retryCount = 0;
this.channelCache.set(channelId, entry);
this.emit('dataManager:channelUpdated', {
channelId,
metrics,
timestamp: new Date()
});
return metrics;
}
catch (error) {
entry.error = error instanceof Error ? error : new Error('Unknown channel error');
entry.retryCount++;
entry.lastUpdate = new Date();
this.channelCache.set(channelId, entry);
this.emit('dataManager:channelError', {
channelId,
error: entry.error,
retryCount: entry.retryCount,
timestamp: new Date()
});
throw entry.error;
}
}
scheduleNextCollection() {
if (!this.isRunning)
return;
this.refreshTimer = setTimeout(async () => {
if (this.isRunning) {
await this.collectData();
this.scheduleNextCollection();
}
}, this.config.refreshInterval);
}
setRefreshInterval(intervalMs) {
this.config.refreshInterval = intervalMs;
if (this.isRunning) {
this.stop();
this.start();
}
this.emit('dataManager:configUpdated', {
refreshInterval: intervalMs,
timestamp: new Date()
});
}
getConfig() {
return { ...this.config };
}
getStats() {
let activeChannels = 0;
let errorChannels = 0;
for (const entry of this.channelCache.values()) {
if (entry.metrics) {
activeChannels++;
}
if (entry.error) {
errorChannels++;
}
}
return {
isRunning: this.isRunning,
channelCount: this.config.channels.length,
lastCollectionTime: this.lastCollectionTime,
cacheStats: {
totalEntries: this.channelCache.size,
activeChannels,
errorChannels
}
};
}
clearCache() {
this.channelCache.clear();
this.emit('dataManager:cacheCleared', {
timestamp: new Date()
});
}
destroy() {
this.stop();
this.clearCache();
this.removeAllListeners();
}
}
exports.DataManager = DataManager;
//# sourceMappingURL=data-manager.js.map