Skip to content

Commit 1fb8370

Browse files
authored
fix: memory leaks, bugs and logic fixes (#46)
1 parent 671dda9 commit 1fb8370

9 files changed

Lines changed: 28 additions & 13 deletions

src/NetworkScoresCalculator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
WebRTCStatsParsed,
77
NetworkQualityStatsSample,
88
} from './types';
9-
import { scheduleTask } from './utils/tasks';
9+
import { createTaskScheduler } from './utils/tasks';
1010
import { CLEANUP_PREV_STATS_TTL_MS } from './utils/constants';
1111

1212
type MosCalculatorResult = {
@@ -17,13 +17,15 @@ type MosCalculatorResult = {
1717
class NetworkScoresCalculator implements INetworkScoresCalculator {
1818
#lastProcessedStats: { [connectionId: string]: WebRTCStatsParsed } = {};
1919

20+
readonly #scheduleTask = createTaskScheduler();
21+
2022
calculate(data: WebRTCStatsParsed): NetworkScores {
2123
const { connection: { id: connectionId } } = data;
2224
const { mos: outbound, stats: outboundStatsSample } = this.calculateOutboundScore(data) || {};
2325
const { mos: inbound, stats: inboundStatsSample } = this.calculateInboundScore(data) || {};
2426
this.#lastProcessedStats[connectionId] = data;
2527

26-
scheduleTask({
28+
this.#scheduleTask({
2729
taskId: connectionId,
2830
delayMs: CLEANUP_PREV_STATS_TTL_MS,
2931
callback: () => (delete this.#lastProcessedStats[connectionId]),

src/detectors/BaseIssueDetector.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
WebRTCStatsParsed,
66
WebRTCStatsParsedWithNetworkScores,
77
} from '../types';
8-
import { scheduleTask } from '../utils/tasks';
8+
import { createTaskScheduler } from '../utils/tasks';
99
import { CLEANUP_PREV_STATS_TTL_MS, MAX_PARSED_STATS_STORAGE_SIZE } from '../utils/constants';
1010

1111
export interface PrevStatsCleanupPayload {
@@ -25,6 +25,8 @@ abstract class BaseIssueDetector implements IssueDetector {
2525

2626
readonly #maxParsedStatsStorageSize: number;
2727

28+
readonly #scheduleTask = createTaskScheduler();
29+
2830
constructor(params: BaseIssueDetectorParams = {}) {
2931
this.#statsCleanupDelayMs = params.statsCleanupTtlMs ?? CLEANUP_PREV_STATS_TTL_MS;
3032
this.#maxParsedStatsStorageSize = params.maxParsedStatsStorageSize ?? MAX_PARSED_STATS_STORAGE_SIZE;
@@ -57,7 +59,7 @@ abstract class BaseIssueDetector implements IssueDetector {
5759
return;
5860
}
5961

60-
scheduleTask({
62+
this.#scheduleTask({
6163
taskId: connectionId,
6264
delayMs: this.#statsCleanupDelayMs,
6365
callback: () => {

src/detectors/InboundNetworkIssueDetector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class InboundNetworkIssueDetector extends BaseIssueDetector {
2323
readonly #highRttThresholdMs: number;
2424

2525
constructor(params: InboundNetworkIssueDetectorParams = {}) {
26-
super();
26+
super(params);
2727
this.#highPacketLossThresholdPct = params.highPacketLossThresholdPct ?? 5;
2828
this.#highJitterThreshold = params.highJitterThreshold ?? 200;
2929
this.#highJitterBufferDelayThresholdMs = params.highJitterBufferDelayThresholdMs ?? 500;

src/detectors/NetworkMediaSyncIssueDetector.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class NetworkMediaSyncIssueDetector extends BaseIssueDetector {
1414
readonly #correctedSamplesThresholdPct: number;
1515

1616
constructor(params: NetworkMediaSyncIssueDetectorParams = {}) {
17-
super();
17+
super(params);
1818
this.#correctedSamplesThresholdPct = params.correctedSamplesThresholdPct ?? 5;
1919
}
2020

@@ -47,6 +47,11 @@ class NetworkMediaSyncIssueDetector extends BaseIssueDetector {
4747
}
4848

4949
const deltaSamplesReceived = stats.track.totalSamplesReceived - previousStreamStats.track.totalSamplesReceived;
50+
51+
if (deltaSamplesReceived === 0) {
52+
return;
53+
}
54+
5055
const deltaCorrectedSamples = nowCorrectedSamples - lastCorrectedSamples;
5156
const correctedSamplesPct = Math.round((deltaCorrectedSamples * 100) / deltaSamplesReceived);
5257
const statsSample = {

src/detectors/OutboundNetworkIssueDetector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class OutboundNetworkIssueDetector extends BaseIssueDetector {
1717
readonly #highJitterThreshold: number;
1818

1919
constructor(params: OutboundNetworkIssueDetectorParams = {}) {
20-
super();
20+
super(params);
2121
this.#highPacketLossThresholdPct = params.highPacketLossThresholdPct ?? 5;
2222
this.#highJitterThreshold = params.highJitterThreshold ?? 200;
2323
}
@@ -79,7 +79,7 @@ class OutboundNetworkIssueDetector extends BaseIssueDetector {
7979
const isHighPacketsLoss = packetLossPct > this.#highPacketLossThresholdPct;
8080
const isHighJitter = avgJitter >= this.#highJitterThreshold;
8181
const isNetworkMediaLatencyIssue = isHighPacketsLoss && isHighJitter;
82-
const isNetworkIssue = (!isHighPacketsLoss && isHighJitter) || isHighJitter || isHighPacketsLoss;
82+
const isNetworkIssue = isHighJitter || isHighPacketsLoss;
8383

8484
const statsSample = {
8585
rtt,

src/helpers/calc.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ export const calculateVolatility = (values: number[]) => {
1515
}
1616

1717
const mean = calculateMean(values);
18+
19+
if (mean === 0) {
20+
return 0;
21+
}
22+
1823
const meanAbsoluteDeviationFps = values.reduce((acc, val) => acc + Math.abs(val - mean), 0) / values.length;
1924
return (meanAbsoluteDeviationFps * 100) / mean;
2025
};

src/helpers/streams.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export const isDtxLikeBehavior = (
77
stdDevThreshold = 30,
88
): boolean => {
99
const frameIntervals: number[] = [];
10-
for (let i = 1; i < allProcessedStats.length - 1; i += 1) {
10+
11+
for (let i = 1; i < allProcessedStats.length; i += 1) {
1112
const videoStreamStats = allProcessedStats[i]?.video?.inbound.find(
1213
(stream) => stream.ssrc === ssrc,
1314
);

src/parser/RTCStatsParser.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
Logger,
1616
} from '../types';
1717
import { checkIsConnectionClosed, calcBitrate } from './utils';
18-
import { scheduleTask } from '../utils/tasks';
18+
import { createTaskScheduler } from '../utils/tasks';
1919
import { CLEANUP_PREV_STATS_TTL_MS } from '../utils/constants';
2020

2121
interface PrevStatsItem {
@@ -31,6 +31,8 @@ interface WebRTCStatsParserParams {
3131
class RTCStatsParser implements StatsParser {
3232
private readonly prevStats = new Map<string, PrevStatsItem | undefined>();
3333

34+
private readonly scheduleTask = createTaskScheduler();
35+
3436
private readonly allowedReportTypes: Set<RTCStatsType> = new Set<RTCStatsType>([
3537
'candidate-pair',
3638
'inbound-rtp',
@@ -133,7 +135,7 @@ class RTCStatsParser implements StatsParser {
133135
ts: Date.now(),
134136
});
135137

136-
scheduleTask({
138+
this.scheduleTask({
137139
taskId: connectionId,
138140
delayMs: CLEANUP_PREV_STATS_TTL_MS,
139141
callback: () => (this.prevStats.delete(connectionId)),

src/utils/tasks.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,3 @@ export const createTaskScheduler = () => {
2626
scheduledTasks.set(taskId, newTimer);
2727
};
2828
};
29-
30-
export const scheduleTask = createTaskScheduler();

0 commit comments

Comments
 (0)