eyevinn-channel-engine 3.3.5 → 3.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM node:slim
1
+ FROM node:12.16.1-alpine
2
2
 
3
3
  WORKDIR /app
4
4
 
package/engine/session.js CHANGED
@@ -512,7 +512,7 @@ class Session {
512
512
  }
513
513
 
514
514
  const sessionState = await this._sessionState.getValues(["vodMediaSeqVideo", "discSeq"]);
515
- const playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
515
+ let playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
516
516
 
517
517
  if (this.prevVodMediaSeq.video === null) {
518
518
  this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
@@ -522,13 +522,20 @@ class Session {
522
522
  }
523
523
 
524
524
  if (playheadState.vodMediaSeqVideo > sessionState.vodMediaSeqVideo) {
525
- debug(`[${this._sessionId}]: Recently Loaded Next Vod. PlayheadState not up-to-date. Return the last generated m3u8`);
526
- const m3u8 = await this._playheadState.getLastM3u8();
527
- if (m3u8) {
528
- this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
529
- return m3u8;
525
+ const state = await this._sessionState.get("state");
526
+ if ([SessionState.VOD_RELOAD_INIT, SessionState.VOD_RELOAD_INITIATING].includes(state)) {
527
+ debug(`[${this._sessionId}]: Recently reloaded Vod. PlayheadState not up-to-date (${playheadState.vodMediaSeqVideo}_${sessionState.vodMediaSeqVideo}). Waiting 500ms before reading from store again`);
528
+ await timer(500);
529
+ playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
530
530
  } else {
531
- debug(`[${this._sessionId}]: We don't have any previously generated m3u8`);
531
+ debug(`[${this._sessionId}]: Recently Loaded Next Vod. PlayheadState not up-to-date. Return the last generated m3u8`);
532
+ const m3u8 = await this._playheadState.getLastM3u8();
533
+ if (m3u8) {
534
+ this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
535
+ return m3u8;
536
+ } else {
537
+ debug(`[${this._sessionId}]: We don't have any previously generated m3u8`);
538
+ }
532
539
  }
533
540
  }
534
541
 
@@ -85,7 +85,7 @@ class SessionLive {
85
85
  if (resetDelay === null || resetDelay < 0) {
86
86
  resetDelay = RESET_DELAY;
87
87
  }
88
-
88
+ debug(`[${this.instanceId}][${this.sessionId}]: LEADER: Resetting SessionLive values in Store ${resetDelay === 0 ? "Immediately" : `after a delay=(${resetDelay}ms)`}`);
89
89
  await timer(resetDelay);
90
90
  await this.sessionLiveState.set("liveSegsForFollowers", null);
91
91
  await this.sessionLiveState.set("lastRequestedMediaSeqRaw", null);
@@ -95,7 +95,7 @@ class SessionLive {
95
95
  mediaSeqCount: null,
96
96
  discSeqCount: null,
97
97
  });
98
- debug(`[${this.instanceId}][${this.sessionId}]: LEADER: Resetting SessionLive values in Store ${resetDelay === 0 ? "Immediately" : `after a delay=(${resetDelay}ms)`}`);
98
+ debug(`[${this.instanceId}][${this.sessionId}]: LEADER: SessionLive values in Store have now been reset!`);
99
99
  }
100
100
 
101
101
  async resetSession() {
@@ -562,6 +562,18 @@ class SessionLive {
562
562
  let attempts = 10;
563
563
  // CHECK AGAIN CASE 1: Store Empty
564
564
  while (!leadersMediaSeqRaw && attempts > 0) {
565
+ if (!leadersMediaSeqRaw) {
566
+ isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
567
+ if (isLeader) {
568
+ debug(`[${this.instanceId}]: I'm the new leader`);
569
+ return;
570
+ }
571
+ }
572
+
573
+ if (!this.allowedToSet) {
574
+ debug(`[${this.sessionId}]: We are about to switch away from LIVE. Abort fetching from Store`);
575
+ break;
576
+ }
565
577
  const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
566
578
  const waitTimeMs = parseInt(segDur / 3, 10);
567
579
  debug(`[${this.sessionId}]: FOLLOWER: Leader has not put anything in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
@@ -572,42 +584,45 @@ class SessionLive {
572
584
  }
573
585
 
574
586
  if (!leadersMediaSeqRaw) {
575
- isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
576
- if (isLeader) {
577
- debug(`[${this.instanceId}]: I'm the new leader`);
578
- return;
579
- } else {
580
- debug(`[${this.instanceId}]: The leader is still alive`);
581
- return;
582
- }
587
+ debug(`[${this.instanceId}]: The leader is still alive`);
588
+ return;
583
589
  }
584
590
 
591
+ let liveSegsInStore = await this.sessionLiveState.get("liveSegsForFollowers");
585
592
  attempts = 10;
586
593
  // CHECK AGAIN CASE 2: Store Old
587
- while (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw && attempts > 0) {
594
+ while ((leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw && attempts > 0) || (this._containsSegment(this.liveSegsForFollowers, liveSegsInStore) && attempts > 0)) {
595
+ if (!this.allowedToSet) {
596
+ debug(`[${this.sessionId}]: We are about to switch away from LIVE. Abort fetching from Store`);
597
+ break;
598
+ }
599
+ if (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw) {
600
+ isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
601
+ if (isLeader) {
602
+ debug(`[${this.instanceId}][${this.sessionId}]: I'm the new leader`);
603
+ return;
604
+ }
605
+ }
606
+ if (this._containsSegment(this.liveSegsForFollowers, liveSegsInStore)) {
607
+ debug(`[${this.sessionId}]: FOLLOWER: _containsSegment=true,${leadersMediaSeqRaw},${this.lastRequestedMediaSeqRaw}`);
608
+ }
588
609
  const segDur = this._getAnyFirstSegmentDurationMs() || DEFAULT_PLAYHEAD_INTERVAL_MS;
589
610
  const waitTimeMs = parseInt(segDur / 3, 10);
590
611
  debug(`[${this.sessionId}]: FOLLOWER: Cannot find anything NEW in store... Will check again in ${waitTimeMs}ms (Tries left=[${attempts}])`);
591
612
  await timer(waitTimeMs);
592
613
  this.timerCompensation = false;
593
614
  leadersMediaSeqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
615
+ liveSegsInStore = await this.sessionLiveState.get("liveSegsForFollowers");
594
616
  attempts--;
595
617
  }
596
-
618
+ // FINALLY
597
619
  if (leadersMediaSeqRaw <= this.lastRequestedMediaSeqRaw) {
598
- isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
599
- if (isLeader) {
600
- debug(`[${this.instanceId}][${this.sessionId}]: I'm the new leader`);
601
- return;
602
- } else {
603
- debug(`[${this.instanceId}][${this.sessionId}]: The leader is still alive`);
604
- return;
605
- }
620
+ debug(`[${this.instanceId}][${this.sessionId}]: The leader is still alive`);
621
+ return;
606
622
  }
607
-
608
623
  // Follower updates its manifest building blocks (segment holders & counts)
609
624
  this.lastRequestedMediaSeqRaw = leadersMediaSeqRaw;
610
- this.liveSegsForFollowers = await this.sessionLiveState.get("liveSegsForFollowers");
625
+ this.liveSegsForFollowers = liveSegsInStore;
611
626
  debug(`[${this.sessionId}]: These are the segments from store: [${JSON.stringify(this.liveSegsForFollowers)}]`);
612
627
  this._updateLiveSegQueue();
613
628
  return;
@@ -807,7 +822,7 @@ class SessionLive {
807
822
  const leadersCurrentMseqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
808
823
  const counts = await this.sessionLiveState.get("firstCounts");
809
824
  const leadersFirstMseqRaw = counts.liveSourceMseqCount;
810
- if (leadersCurrentMseqRaw !== null && leadersCurrentMseqRaw !== currentMseqRaw) {
825
+ if (leadersCurrentMseqRaw !== null && leadersCurrentMseqRaw > currentMseqRaw) {
811
826
  // if leader never had any segs from prev mseq
812
827
  if (leadersFirstMseqRaw !== null && leadersFirstMseqRaw === leadersCurrentMseqRaw) {
813
828
  // Follower updates it's manifest ingedients (segment holders & counts)
@@ -855,8 +870,8 @@ class SessionLive {
855
870
  // Do not replace old data with empty data
856
871
  if (segListSize > 0) {
857
872
  debug(`[${this.sessionId}]: LEADER: Adding data to store!`);
858
- await this.sessionLiveState.set("liveSegsForFollowers", this.liveSegsForFollowers);
859
873
  await this.sessionLiveState.set("lastRequestedMediaSeqRaw", this.lastRequestedMediaSeqRaw);
874
+ await this.sessionLiveState.set("liveSegsForFollowers", this.liveSegsForFollowers);
860
875
  }
861
876
  }
862
877
 
@@ -1435,6 +1450,26 @@ class SessionLive {
1435
1450
  }
1436
1451
  return true;
1437
1452
  }
1453
+
1454
+ _containsSegment(segments, newSegments) {
1455
+ if (!segments || !newSegments) {
1456
+ return false;
1457
+ }
1458
+ if (Object.keys(segments).length === 0 || Object.keys(newSegments).length === 0) {
1459
+ return false;
1460
+ }
1461
+ const someBw = Object.keys(segments)[0];
1462
+ const segList = segments[someBw];
1463
+ const mostRecentSegment = segList[segList.length - 1];
1464
+
1465
+ const segListNew = newSegments[someBw];
1466
+ const mostRecentSegmentNew = segListNew[segListNew.length - 1];
1467
+
1468
+ if (mostRecentSegmentNew.uri === mostRecentSegment.uri) {
1469
+ return true;
1470
+ }
1471
+ return false;
1472
+ }
1438
1473
  }
1439
1474
 
1440
1475
  module.exports = SessionLive;
@@ -307,9 +307,6 @@ class StreamSwitcher {
307
307
  liveSegments = await sessionLive.getCurrentMediaSequenceSegments();
308
308
  liveCounts = await sessionLive.getCurrentMediaAndDiscSequenceCount();
309
309
 
310
- await sessionLive.resetSession();
311
- sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
312
-
313
310
  if (scheduleObj && !scheduleObj.duration) {
314
311
  debug(`[${this.sessionId}]: Cannot switch VOD. No duration specified for schedule item: [${scheduleObj.assetId}]`);
315
312
  }
@@ -331,6 +328,9 @@ class StreamSwitcher {
331
328
  await session.setCurrentMediaAndDiscSequenceCount(liveCounts.mediaSeq, liveCounts.discSeq);
332
329
  await session.setCurrentMediaSequenceSegments(liveSegments.currMseqSegs, liveSegments.segCount);
333
330
 
331
+ await sessionLive.resetSession();
332
+ sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
333
+
334
334
  this.working = false;
335
335
  this.streamTypeLive = false;
336
336
  debug(`[${this.sessionId}]: [ Switched from LIVE->V2L ]`);
@@ -349,8 +349,6 @@ class StreamSwitcher {
349
349
  this.eventId = scheduleObj.eventId;
350
350
  liveSegments = await sessionLive.getCurrentMediaSequenceSegments();
351
351
  liveCounts = await sessionLive.getCurrentMediaAndDiscSequenceCount();
352
- await sessionLive.resetSession();
353
- sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
354
352
 
355
353
  eventSegments = await session.getTruncatedVodSegments(scheduleObj.uri, scheduleObj.duration / 1000);
356
354
  if (!eventSegments) {
@@ -369,9 +367,11 @@ class StreamSwitcher {
369
367
  const prerollSegments = this.prerollsCache[this.sessionId].segments;
370
368
  eventSegments = this._mergeSegments(prerollSegments, eventSegments, true);
371
369
  }
372
-
373
370
  await session.setCurrentMediaSequenceSegments(eventSegments, 0, true);
374
371
 
372
+ await sessionLive.resetSession();
373
+ sessionLive.resetLiveStoreAsync(RESET_DELAY); // In parallel
374
+
375
375
  this.working = false;
376
376
  this.streamTypeLive = false;
377
377
  debug(`[${this.sessionId}]: Switched from LIVE->VOD`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyevinn-channel-engine",
3
- "version": "3.3.5",
3
+ "version": "3.3.8",
4
4
  "description": "OTT TV Channel Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {