eyevinn-channel-engine 3.1.4 → 3.1.7
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/engine/session.js +39 -10
- package/engine/session_live.js +26 -14
- package/package.json +1 -1
package/engine/session.js
CHANGED
|
@@ -44,6 +44,8 @@ class Session {
|
|
|
44
44
|
this.maxTickInterval = DEFAULT_MAX_TICK_INTERVAL;
|
|
45
45
|
this.diffCompensation = null;
|
|
46
46
|
this.waitingForNextVod = false;
|
|
47
|
+
this.leaderIsSettingNextVod = false;
|
|
48
|
+
this.isSwitchingBackFromLive = false;
|
|
47
49
|
|
|
48
50
|
if (config) {
|
|
49
51
|
if (config.sessionId) {
|
|
@@ -258,6 +260,8 @@ class Session {
|
|
|
258
260
|
throw new Error('Session not ready');
|
|
259
261
|
}
|
|
260
262
|
|
|
263
|
+
this.isSwitchingBackFromLive = true;
|
|
264
|
+
|
|
261
265
|
let isLeader = await this._sessionStateStore.isLeader(this._instanceId);
|
|
262
266
|
if (!isLeader) {
|
|
263
267
|
debug(`[${this._sessionId}]: FOLLOWER: Invalidate cache to ensure having the correct VOD!`);
|
|
@@ -278,6 +282,7 @@ class Session {
|
|
|
278
282
|
if (!isLeader || vodReloaded) {
|
|
279
283
|
debug(`[${this._sessionId}]: FOLLOWER: leader is alive, and has presumably updated currentVod. Clearing the cache now`);
|
|
280
284
|
await this._sessionState.clearCurrentVodCache();
|
|
285
|
+
this.isSwitchingBackFromLive = false;
|
|
281
286
|
return;
|
|
282
287
|
}
|
|
283
288
|
}
|
|
@@ -313,6 +318,7 @@ class Session {
|
|
|
313
318
|
await this._playheadState.set("vodMediaSeqAudio", 0);
|
|
314
319
|
await this._playheadState.set("playheadRef", Date.now());
|
|
315
320
|
}
|
|
321
|
+
this.isSwitchingBackFromLive = false;
|
|
316
322
|
}
|
|
317
323
|
|
|
318
324
|
async getCurrentMediaSequenceSegments() {
|
|
@@ -350,6 +356,9 @@ class Session {
|
|
|
350
356
|
if (!this._sessionState) {
|
|
351
357
|
throw new Error('Session not ready');
|
|
352
358
|
}
|
|
359
|
+
|
|
360
|
+
this.isSwitchingBackFromLive = true;
|
|
361
|
+
|
|
353
362
|
const isLeader = await this._sessionStateStore.isLeader(this._instanceId);
|
|
354
363
|
if (isLeader) {
|
|
355
364
|
await this._sessionState.set("mediaSeq", _mediaSeq);
|
|
@@ -357,6 +366,7 @@ class Session {
|
|
|
357
366
|
await this._sessionState.set("discSeq", _discSeq);
|
|
358
367
|
debug(`[${this._sessionId}]: Setting current media and discontinuity count -> [${_mediaSeq}]:[${_discSeq}]`);
|
|
359
368
|
}
|
|
369
|
+
this.isSwitchingBackFromLive = false;
|
|
360
370
|
}
|
|
361
371
|
|
|
362
372
|
async getCurrentMediaAndDiscSequenceCount() {
|
|
@@ -395,6 +405,15 @@ class Session {
|
|
|
395
405
|
if (!this._sessionState) {
|
|
396
406
|
throw new Error('Session not ready');
|
|
397
407
|
}
|
|
408
|
+
// Be sure that the leader is not in the middle of setting new vod data in store.
|
|
409
|
+
// Followers will never run this part...
|
|
410
|
+
let tries = 4;
|
|
411
|
+
while(tries > 0 && this.leaderIsSettingNextVod) {
|
|
412
|
+
debug(`[${this._sessionId}]: Leader is setting the next vod. Waiting 500ms_${tries}`);
|
|
413
|
+
await timer(500);
|
|
414
|
+
tries--;
|
|
415
|
+
}
|
|
416
|
+
|
|
398
417
|
const sessionState = await this._sessionState.getValues(["vodMediaSeqVideo", "discSeq"]);
|
|
399
418
|
const playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo"]);
|
|
400
419
|
|
|
@@ -463,6 +482,14 @@ class Session {
|
|
|
463
482
|
async incrementAsync() {
|
|
464
483
|
await this._tickAsync();
|
|
465
484
|
const isLeader = await this._sessionStateStore.isLeader(this._instanceId);
|
|
485
|
+
// Avoid reading old values if new ones are on their way...
|
|
486
|
+
let tries = 10;
|
|
487
|
+
while (tries > 0 && this.isSwitchingBackFromLive) {
|
|
488
|
+
debug(`[${this._sessionId}]: Leader is currently setting new data in store. Waiting 500ms_${tries}`);
|
|
489
|
+
await timer(500);
|
|
490
|
+
tries--;
|
|
491
|
+
}
|
|
492
|
+
|
|
466
493
|
let sessionState = await this._sessionState.getValues(
|
|
467
494
|
["state", "mediaSeq", "discSeq", "vodMediaSeqVideo", "vodMediaSeqAudio"]);
|
|
468
495
|
let playheadState = await this._playheadState.getValues(["mediaSeq", "vodMediaSeqVideo", "vodMediaSeqAudio"]);
|
|
@@ -498,7 +525,7 @@ class Session {
|
|
|
498
525
|
sessionState.vodMediaSeqVideo = await this._sessionState.increment("vodMediaSeqVideo");
|
|
499
526
|
sessionState.vodMediaSeqAudio = await this._sessionState.increment("vodMediaSeqAudio");
|
|
500
527
|
}
|
|
501
|
-
|
|
528
|
+
|
|
502
529
|
if (sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1) {
|
|
503
530
|
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", currentVod.getLiveMediaSequencesCount() - 1);
|
|
504
531
|
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", currentVod.getLiveMediaSequencesCount() - 1);
|
|
@@ -739,11 +766,10 @@ class Session {
|
|
|
739
766
|
length = currentVod.getLiveMediaSequencesCount();
|
|
740
767
|
lastDiscontinuity = currentVod.getLastDiscontinuity();
|
|
741
768
|
}
|
|
742
|
-
await this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING);
|
|
743
|
-
await this._sessionState.setCurrentVod(slateVod);
|
|
744
|
-
|
|
745
769
|
await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
746
770
|
await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
771
|
+
await this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING);
|
|
772
|
+
await this._sessionState.setCurrentVod(slateVod);
|
|
747
773
|
await this._sessionState.set("mediaSeq", sessionState.mediaSeq + length);
|
|
748
774
|
await this._sessionState.set("discSeq", sessionState.discSeq + lastDiscontinuity);
|
|
749
775
|
await this._sessionState.set("slateCount", sessionState.slateCount + 1);
|
|
@@ -827,6 +853,10 @@ class Session {
|
|
|
827
853
|
debug(`[${this._sessionId}]: ${currentVod.getDeltaTimes()}`);
|
|
828
854
|
debug(`[${this._sessionId}]: ${currentVod.getPlayheadPositions()}`);
|
|
829
855
|
//debug(newVod);
|
|
856
|
+
sessionState.mediaSeq = await this._sessionState.set("mediaSeq", 0);
|
|
857
|
+
sessionState.discSeq = await this._sessionState.set("discSeq", 0);
|
|
858
|
+
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
859
|
+
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
830
860
|
await this._playheadState.set("playheadRef", Date.now());
|
|
831
861
|
this.produceEvent({
|
|
832
862
|
type: 'NOW_PLAYING',
|
|
@@ -837,10 +867,6 @@ class Session {
|
|
|
837
867
|
});
|
|
838
868
|
sessionState.state = await this._sessionState.set("state", SessionState.VOD_PLAYING);
|
|
839
869
|
sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
|
|
840
|
-
sessionState.mediaSeq = await this._sessionState.set("mediaSeq", 0);
|
|
841
|
-
sessionState.discSeq = await this._sessionState.set("discSeq", 0);
|
|
842
|
-
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
843
|
-
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
844
870
|
await this._sessionState.remove("nextVod");
|
|
845
871
|
return;
|
|
846
872
|
} else {
|
|
@@ -944,16 +970,19 @@ class Session {
|
|
|
944
970
|
await ChaosMonkey.loadVod(loadPromise);
|
|
945
971
|
cloudWatchLog(!this.cloudWatchLogging, 'engine-session',
|
|
946
972
|
{ event: 'loadVod', channel: this._sessionId, loadTimeMs: Date.now() - loadStart });
|
|
973
|
+
this.leaderIsSettingNextVod = true;
|
|
947
974
|
debug(`[${this._sessionId}]: next VOD loaded (${newVod.getDeltaTimes()})`);
|
|
948
975
|
debug(`[${this._sessionId}]: ${newVod.getPlayheadPositions()}`);
|
|
949
976
|
currentVod = newVod;
|
|
950
977
|
debug(`[${this._sessionId}]: msequences=${currentVod.getLiveMediaSequencesCount()}`);
|
|
951
|
-
await this._sessionState.remove("nextVod");
|
|
952
|
-
sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
|
|
953
978
|
sessionState.vodMediaSeqVideo = await this._sessionState.set("vodMediaSeqVideo", 0);
|
|
954
979
|
sessionState.vodMediaSeqAudio = await this._sessionState.set("vodMediaSeqAudio", 0);
|
|
955
980
|
sessionState.mediaSeq = await this._sessionState.set("mediaSeq", sessionState.mediaSeq + length);
|
|
956
981
|
sessionState.discSeq = await this._sessionState.set("discSeq", sessionState.discSeq + lastDiscontinuity);
|
|
982
|
+
debug(`[${this._sessionId}]: new sequence data set in store [${sessionState.mediaSeq}][${sessionState.discSeq}]`);
|
|
983
|
+
await this._sessionState.remove("nextVod");
|
|
984
|
+
sessionState.currentVod = await this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 });
|
|
985
|
+
this.leaderIsSettingNextVod = false;
|
|
957
986
|
await this._playheadState.set("playheadRef", Date.now());
|
|
958
987
|
this.produceEvent({
|
|
959
988
|
type: 'NOW_PLAYING',
|
package/engine/session_live.js
CHANGED
|
@@ -499,8 +499,14 @@ class SessionLive {
|
|
|
499
499
|
if (!this.liveSegQueue[liveBw]) {
|
|
500
500
|
this.liveSegQueue[liveBw] = [];
|
|
501
501
|
}
|
|
502
|
-
|
|
503
|
-
|
|
502
|
+
// Do not push duplicates
|
|
503
|
+
const liveSegURIs = this.liveSegQueue[liveBw].filter(seg => seg.uri).map(seg => seg.uri);
|
|
504
|
+
if (liveSegFromLeader.uri && liveSegURIs.includes(liveSegFromLeader.uri)) {
|
|
505
|
+
debug(`[${this.sessionId}]: FOLLOWER: Found duplicate live segment. Skip push!`);
|
|
506
|
+
} else {
|
|
507
|
+
this.liveSegQueue[liveBw].push(liveSegFromLeader);
|
|
508
|
+
debug(`[${this.sessionId}]: FOLLOWER: Pushed segment (${liveSegFromLeader.uri ? liveSegFromLeader.uri : "Disc-tag"}) to 'liveSegQueue' (${liveBw})`);
|
|
509
|
+
}
|
|
504
510
|
}
|
|
505
511
|
}
|
|
506
512
|
// Remove older segments and update counts
|
|
@@ -520,13 +526,13 @@ class SessionLive {
|
|
|
520
526
|
*/
|
|
521
527
|
async _loadAllMediaManifests() {
|
|
522
528
|
debug(`[${this.sessionId}]: Attempting to load all media manifest URIs in=${Object.keys(this.mediaManifestURIs)}`);
|
|
523
|
-
|
|
529
|
+
let currentMseqRaw = null;
|
|
524
530
|
// -------------------------------------
|
|
525
531
|
// If I am a Follower-node then my job
|
|
526
532
|
// ends here, where I only read from store.
|
|
527
533
|
// -------------------------------------
|
|
528
534
|
let isLeader = await this.sessionLiveStateStore.isLeader(this.instanceId);
|
|
529
|
-
if (!isLeader && this.lastRequestedMediaSeqRaw) {
|
|
535
|
+
if (!isLeader && this.lastRequestedMediaSeqRaw !== null) {
|
|
530
536
|
debug(`[${this.sessionId}]: FOLLOWER: Reading data from store!`);
|
|
531
537
|
|
|
532
538
|
let leadersMediaSeqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
|
|
@@ -659,6 +665,8 @@ class SessionLive {
|
|
|
659
665
|
continue;
|
|
660
666
|
}
|
|
661
667
|
|
|
668
|
+
currentMseqRaw = allMediaSeqCounts[0];
|
|
669
|
+
|
|
662
670
|
if (!isLeader) {
|
|
663
671
|
let leadersFirstSeqCounts = await this.sessionLiveState.get("firstCounts");
|
|
664
672
|
let tries = 20;
|
|
@@ -687,9 +695,13 @@ class SessionLive {
|
|
|
687
695
|
|
|
688
696
|
// Respawners never do this, only starter followers.
|
|
689
697
|
// Edge Case: FOLLOWER transitioned from session with different segments from LEADER
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
698
|
+
if (leadersFirstSeqCounts.discSeqCount !== this.discSeqCount) {
|
|
699
|
+
this.discSeqCount = leadersFirstSeqCounts.discSeqCount;
|
|
700
|
+
}
|
|
701
|
+
if (leadersFirstSeqCounts.mediaSeqCount !== this.mediaSeqCount) {
|
|
702
|
+
this.mediaSeqCount = leadersFirstSeqCounts.mediaSeqCount;
|
|
703
|
+
debug(`[${this.sessionId}]: FOLLOWER transistioned with wrong V2L segments, updating counts to [${
|
|
704
|
+
this.mediaSeqCount}][${this.discSeqCount}], and reading 'transitSegs' from store`);
|
|
693
705
|
const transitSegs = await this.sessionLiveState.get("transitSegs");
|
|
694
706
|
if (!this._isEmpty(transitSegs)) {
|
|
695
707
|
this.vodSegments = transitSegs;
|
|
@@ -697,12 +709,12 @@ class SessionLive {
|
|
|
697
709
|
}
|
|
698
710
|
|
|
699
711
|
// Prepare to load segments...
|
|
700
|
-
debug(`[${this.instanceId}][${this.sessionId}]: Newest mseq from LIVE=${
|
|
701
|
-
if (
|
|
712
|
+
debug(`[${this.instanceId}][${this.sessionId}]: Newest mseq from LIVE=${currentMseqRaw} First mseq in store=${leadersFirstSeqCounts.liveSourceMseqCount}`);
|
|
713
|
+
if (currentMseqRaw === leadersFirstSeqCounts.liveSourceMseqCount) {
|
|
702
714
|
this.pushAmount = 1; // Follower from start
|
|
703
715
|
} else {
|
|
704
716
|
// RESPAWNED NODES
|
|
705
|
-
this.pushAmount =
|
|
717
|
+
this.pushAmount = currentMseqRaw - leadersFirstSeqCounts.liveSourceMseqCount + 1;
|
|
706
718
|
|
|
707
719
|
const transitSegs = await this.sessionLiveState.get("transitSegs");
|
|
708
720
|
//debug(`[${this.sessionId}]: NEW FOLLOWER: I tried to get 'transitSegs'. This is what I found ${JSON.stringify(transitSegs)}`);
|
|
@@ -716,8 +728,8 @@ class SessionLive {
|
|
|
716
728
|
if (this.firstTime) {
|
|
717
729
|
this.pushAmount = 1; // Leader from start
|
|
718
730
|
} else {
|
|
719
|
-
this.pushAmount =
|
|
720
|
-
debug(`[${this.sessionId}]: ...calculating pushAmount=${
|
|
731
|
+
this.pushAmount = currentMseqRaw - this.lastRequestedMediaSeqRaw;
|
|
732
|
+
debug(`[${this.sessionId}]: ...calculating pushAmount=${currentMseqRaw}-${this.lastRequestedMediaSeqRaw}=${this.pushAmount}`);
|
|
721
733
|
}
|
|
722
734
|
debug(`[${this.sessionId}]: ...pushAmount=${this.pushAmount}`);
|
|
723
735
|
break;
|
|
@@ -737,9 +749,9 @@ class SessionLive {
|
|
|
737
749
|
const leadersCurrentMseqRaw = await this.sessionLiveState.get("lastRequestedMediaSeqRaw");
|
|
738
750
|
const counts = await this.sessionLiveState.get("firstCounts");
|
|
739
751
|
const leadersFirstMseqRaw = counts.liveSourceMseqCount;
|
|
740
|
-
if (leadersCurrentMseqRaw && leadersCurrentMseqRaw !==
|
|
752
|
+
if (leadersCurrentMseqRaw !== null && leadersCurrentMseqRaw !== currentMseqRaw) {
|
|
741
753
|
// if leader never had any segs from prev mseq
|
|
742
|
-
if (leadersFirstMseqRaw && leadersFirstMseqRaw === leadersCurrentMseqRaw) {
|
|
754
|
+
if (leadersFirstMseqRaw !== null && leadersFirstMseqRaw === leadersCurrentMseqRaw) {
|
|
743
755
|
// Follower updates it's manifest ingedients (segment holders & counts)
|
|
744
756
|
this.lastRequestedMediaSeqRaw = leadersCurrentMseqRaw;
|
|
745
757
|
this.liveSegsForFollowers = await this.sessionLiveState.get("liveSegsForFollowers");
|