eyevinn-channel-engine 5.0.4 → 5.0.6

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.
@@ -1012,47 +1012,42 @@ var Session = /** @class */ (function () {
1012
1012
  };
1013
1013
  Session.prototype.incrementAsync = function () {
1014
1014
  return __awaiter(this, void 0, void 0, function () {
1015
- var isLeader, sessionState, playheadState, currentVod, _a, isOldVod, nextState, leaderAction, leaderState, _b, m3u8_1, _c, playheadPosVideoMs, playheadAudio, playheadSubtitle, audioSeqLastIdx, sessionStateObj, _d, playheadPosVideo, _e, subtitleSeqLastIdx, sessionStateObj, _f, newSessionState, updatedValues, updatedPlayhead, mediaSequenceValue, audioInfo, mediaSequenceValueAudio, subsInfo, mediaSequenceValueSubtitle, diffMs, m3u8;
1016
- return __generator(this, function (_g) {
1017
- switch (_g.label) {
1015
+ var _a, tickSessionState, isLeader, tickCurrentVod, sessionState, currentVod, playheadState, _b, newSessionState, isOldVod, nextState, leaderAction, leaderState, _c, m3u8_1, playheadPosVideoMs, playheadAudio, playheadSubtitle, audioSeqLastIdx, subtitleSeqLastIdx, playheadData, _d, updatedValues, updatedPlayhead, mediaSequenceValue, audioInfo, mediaSequenceValueAudio, subsInfo, mediaSequenceValueSubtitle, diffMs, m3u8;
1016
+ return __generator(this, function (_e) {
1017
+ switch (_e.label) {
1018
1018
  case 0: return [4 /*yield*/, this._tickAsync()];
1019
1019
  case 1:
1020
- _g.sent();
1021
- return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
1022
- case 2:
1023
- isLeader = _g.sent();
1024
- return [4 /*yield*/, this._sessionState.getValues(["state", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle"])];
1025
- case 3:
1026
- sessionState = _g.sent();
1020
+ _e.sent();
1021
+ _a = this._lastTickState, tickSessionState = _a.sessionState, isLeader = _a.isLeader, tickCurrentVod = _a.currentVod;
1022
+ sessionState = tickSessionState;
1023
+ currentVod = tickCurrentVod;
1027
1024
  return [4 /*yield*/, this._playheadState.getValues(["mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSubtitle", "playheadRef"])];
1028
- case 4:
1029
- playheadState = _g.sent();
1030
- return [4 /*yield*/, this._sessionState.getCurrentVod()];
1031
- case 5:
1032
- currentVod = _g.sent();
1025
+ case 2:
1026
+ playheadState = _e.sent();
1033
1027
  if (!(!currentVod ||
1034
1028
  sessionState.vodMediaSeqVideo === null ||
1035
1029
  sessionState.vodMediaSeqAudio === null ||
1036
1030
  sessionState.vodMediaSeqSubtitle === null ||
1037
1031
  sessionState.state === null ||
1038
1032
  sessionState.mediaSeq === null ||
1039
- sessionState.discSeq === null)) return [3 /*break*/, 9];
1033
+ sessionState.discSeq === null)) return [3 /*break*/, 6];
1040
1034
  debug("[".concat(this._sessionId, "]: Session is not ready yet"));
1041
1035
  debug(sessionState);
1042
1036
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1043
- case 6:
1044
- _g.sent();
1045
- if (!isLeader) return [3 /*break*/, 8];
1037
+ case 3:
1038
+ _e.sent();
1039
+ if (!isLeader) return [3 /*break*/, 5];
1046
1040
  debug("[".concat(this._sessionId, "]: I am the leader, trying to initiate the session"));
1047
- _a = sessionState;
1041
+ _b = sessionState;
1048
1042
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_INIT)];
1049
- case 7:
1050
- _a.state = _g.sent();
1051
- _g.label = 8;
1052
- case 8: return [2 /*return*/, null];
1053
- case 9:
1054
- if (!(sessionState.state === SessionState.VOD_NEXT_INITIATING || sessionState.state === SessionState.VOD_RELOAD_INITIATING)) return [3 /*break*/, 14];
1055
- if (!isLeader) return [3 /*break*/, 11];
1043
+ case 4:
1044
+ _b.state = _e.sent();
1045
+ _e.label = 5;
1046
+ case 5: return [2 /*return*/, null];
1047
+ case 6:
1048
+ newSessionState = {};
1049
+ if (!(sessionState.state === SessionState.VOD_NEXT_INITIATING || sessionState.state === SessionState.VOD_RELOAD_INITIATING)) return [3 /*break*/, 11];
1050
+ if (!isLeader) return [3 /*break*/, 8];
1056
1051
  isOldVod = this._isOldVod(playheadState.playheadRef, currentVod.getDuration());
1057
1052
  nextState = SessionState.VOD_PLAYING;
1058
1053
  if (isOldVod) {
@@ -1061,16 +1056,16 @@ var Session = /** @class */ (function () {
1061
1056
  leaderAction = sessionState.state === SessionState.VOD_NEXT_INITIATING ? "initiated" : "reloaded";
1062
1057
  leaderState = nextState === SessionState.VOD_NEXT_INIT ? "VOD_NEXT_INIT" : "VOD_PLAYING";
1063
1058
  debug("[".concat(this._sessionId, "]: I am the leader and have just ").concat(leaderAction, " next VOD, let's move to ").concat(leaderState));
1064
- _b = sessionState;
1059
+ _c = sessionState;
1065
1060
  return [4 /*yield*/, this._sessionState.set("state", nextState)];
1066
- case 10:
1067
- _b.state = _g.sent();
1068
- return [3 /*break*/, 13];
1069
- case 11:
1061
+ case 7:
1062
+ _c.state = _e.sent();
1063
+ return [3 /*break*/, 10];
1064
+ case 8:
1070
1065
  debug("[".concat(this._sessionId, "]: Return the last generated m3u8 to give the leader some time"));
1071
1066
  return [4 /*yield*/, this._playheadState.getLastM3u8()];
1072
- case 12:
1073
- m3u8_1 = _g.sent();
1067
+ case 9:
1068
+ m3u8_1 = _e.sent();
1074
1069
  if (m3u8_1) {
1075
1070
  return [2 /*return*/, m3u8_1];
1076
1071
  }
@@ -1078,63 +1073,51 @@ var Session = /** @class */ (function () {
1078
1073
  debug("[".concat(this._sessionId, "]: We don't have any previously generated m3u8"));
1079
1074
  }
1080
1075
  this.isAllowedToClearVodCache = true;
1081
- _g.label = 13;
1082
- case 13: return [3 /*break*/, 27];
1083
- case 14:
1084
- _c = sessionState;
1085
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqVideo", 1)];
1086
- case 15:
1087
- _c.vodMediaSeqVideo = _g.sent();
1076
+ _e.label = 10;
1077
+ case 10: return [3 /*break*/, 17];
1078
+ case 11:
1079
+ // Compute increments locally instead of individual Redis round-trips
1080
+ if (isLeader) {
1081
+ debug("[".concat(this._sessionId, "]: I am incrementing key vodMediaSeqVideo with 1"));
1082
+ sessionState.vodMediaSeqVideo += 1;
1083
+ }
1088
1084
  playheadPosVideoMs = void 0;
1089
1085
  playheadAudio = void 0;
1090
1086
  playheadSubtitle = void 0;
1091
1087
  return [4 /*yield*/, this._getCurrentPlayheadPosition()];
1092
- case 16:
1093
- playheadPosVideoMs = (_g.sent()) * 1000;
1094
- if (!this.use_demuxed_audio) return [3 /*break*/, 20];
1088
+ case 12:
1089
+ playheadPosVideoMs = (_e.sent()) * 1000;
1090
+ if (!this.use_demuxed_audio) return [3 /*break*/, 14];
1095
1091
  audioSeqLastIdx = currentVod.getLiveMediaSequencesCount("audio") - 1;
1096
- return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqAudio"])];
1097
- case 17:
1098
- sessionStateObj = _g.sent();
1099
- return [4 /*yield*/, this._determineExtraMediaIncrement("audio", playheadPosVideoMs, audioSeqLastIdx, sessionStateObj.vodMediaSeqAudio, this._getAudioPlayheadPosition.bind(this))];
1100
- case 18:
1101
- playheadAudio = _g.sent();
1102
- // Perform the Increment
1092
+ return [4 /*yield*/, this._determineExtraMediaIncrement("audio", playheadPosVideoMs, audioSeqLastIdx, sessionState.vodMediaSeqAudio, this._getAudioPlayheadPosition.bind(this))];
1093
+ case 13:
1094
+ playheadAudio = _e.sent();
1103
1095
  debug("[".concat(this._sessionId, "]: Will increment audio with ").concat(playheadAudio.increment));
1104
- _d = sessionState;
1105
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqAudio", playheadAudio.increment)];
1106
- case 19:
1107
- _d.vodMediaSeqAudio = _g.sent();
1108
- _g.label = 20;
1109
- case 20:
1110
- if (!this.use_vtt_subtitles) return [3 /*break*/, 26];
1111
- _e = playheadPosVideo;
1112
- if (_e) return [3 /*break*/, 22];
1113
- return [4 /*yield*/, this._getCurrentPlayheadPosition()];
1114
- case 21:
1115
- _e = (_g.sent()) * 1000;
1116
- _g.label = 22;
1117
- case 22:
1118
- playheadPosVideo = _e;
1096
+ if (isLeader) {
1097
+ debug("[".concat(this._sessionId, "]: I am incrementing key vodMediaSeqAudio with ").concat(playheadAudio.increment));
1098
+ sessionState.vodMediaSeqAudio += (playheadAudio.increment === 0 ? 0 : playheadAudio.increment || 1);
1099
+ }
1100
+ _e.label = 14;
1101
+ case 14:
1102
+ if (!this.use_vtt_subtitles) return [3 /*break*/, 16];
1119
1103
  subtitleSeqLastIdx = currentVod.getLiveMediaSequencesCount("subtitle") - 1;
1120
- return [4 /*yield*/, this._sessionState.getValues(["vodMediaSeqSubtitle"])];
1121
- case 23:
1122
- sessionStateObj = _g.sent();
1123
- return [4 /*yield*/, this._determineExtraMediaIncrement("subtitle", playheadPosVideoMs, subtitleSeqLastIdx, sessionStateObj.vodMediaSeqSubtitle, this._getSubtitlePlayheadPosition.bind(this))];
1124
- case 24:
1125
- playheadSubtitle = _g.sent();
1126
- // Perform the Increment
1104
+ return [4 /*yield*/, this._determineExtraMediaIncrement("subtitle", playheadPosVideoMs, subtitleSeqLastIdx, sessionState.vodMediaSeqSubtitle, this._getSubtitlePlayheadPosition.bind(this))];
1105
+ case 15:
1106
+ playheadSubtitle = _e.sent();
1127
1107
  debug("[".concat(this._sessionId, "]: Will increment subtitle with ").concat(playheadSubtitle.increment));
1128
- _f = sessionState;
1129
- return [4 /*yield*/, this._sessionState.increment("vodMediaSeqSubtitle", playheadSubtitle.increment)];
1130
- case 25:
1131
- _f.vodMediaSeqSubtitle = _g.sent();
1132
- _g.label = 26;
1133
- case 26:
1108
+ if (isLeader) {
1109
+ debug("[".concat(this._sessionId, "]: I am incrementing key vodMediaSeqSubtitle with ").concat(playheadSubtitle.increment));
1110
+ sessionState.vodMediaSeqSubtitle += (playheadSubtitle.increment === 0 ? 0 : playheadSubtitle.increment || 1);
1111
+ }
1112
+ _e.label = 16;
1113
+ case 16:
1134
1114
  this._logCurrentPlayheadPositions(playheadPosVideoMs, playheadAudio, playheadSubtitle);
1135
- _g.label = 27;
1136
- case 27:
1137
- newSessionState = {};
1115
+ // Include locally-computed increments in the batch write
1116
+ newSessionState.vodMediaSeqVideo = sessionState.vodMediaSeqVideo;
1117
+ newSessionState.vodMediaSeqAudio = sessionState.vodMediaSeqAudio;
1118
+ newSessionState.vodMediaSeqSubtitle = sessionState.vodMediaSeqSubtitle;
1119
+ _e.label = 17;
1120
+ case 17:
1138
1121
  if (sessionState.vodMediaSeqVideo >= currentVod.getLiveMediaSequencesCount() - 1) {
1139
1122
  newSessionState.vodMediaSeqVideo = currentVod.getLiveMediaSequencesCount() - 1;
1140
1123
  newSessionState.state = SessionState.VOD_NEXT_INIT;
@@ -1149,23 +1132,24 @@ var Session = /** @class */ (function () {
1149
1132
  newSessionState.state = SessionState.VOD_RELOAD_INIT;
1150
1133
  this.isSwitchingBackToV2L = false;
1151
1134
  }
1152
- return [4 /*yield*/, this._sessionState.setValues(newSessionState)];
1153
- case 28:
1154
- updatedValues = _g.sent();
1155
- sessionState = __assign(__assign({}, sessionState), updatedValues);
1156
1135
  if (isLeader) {
1157
1136
  debug("[".concat(this._sessionId, "]: I am the leader, updating PlayheadState values"));
1158
1137
  }
1159
- return [4 /*yield*/, this._playheadState.setValues({
1160
- "mediaSeq": sessionState.mediaSeq,
1161
- "mediaSeqAudio": sessionState.mediaSeqAudio,
1162
- "mediaSeqSubtitle": sessionState.mediaSeqSubtitle,
1163
- "vodMediaSeqVideo": sessionState.vodMediaSeqVideo,
1164
- "vodMediaSeqAudio": sessionState.vodMediaSeqAudio,
1165
- "vodMediaSeqSubtitle": sessionState.vodMediaSeqSubtitle
1166
- }, isLeader)];
1167
- case 29:
1168
- updatedPlayhead = _g.sent();
1138
+ playheadData = {
1139
+ "mediaSeq": sessionState.mediaSeq,
1140
+ "mediaSeqAudio": sessionState.mediaSeqAudio,
1141
+ "mediaSeqSubtitle": sessionState.mediaSeqSubtitle,
1142
+ "vodMediaSeqVideo": sessionState.vodMediaSeqVideo,
1143
+ "vodMediaSeqAudio": sessionState.vodMediaSeqAudio,
1144
+ "vodMediaSeqSubtitle": sessionState.vodMediaSeqSubtitle
1145
+ };
1146
+ return [4 /*yield*/, Promise.all([
1147
+ this._sessionState.setValues(newSessionState),
1148
+ this._playheadState.setValues(playheadData, isLeader)
1149
+ ])];
1150
+ case 18:
1151
+ _d = _e.sent(), updatedValues = _d[0], updatedPlayhead = _d[1];
1152
+ sessionState = __assign(__assign({}, sessionState), updatedValues);
1169
1153
  playheadState = __assign(__assign({}, playheadState), updatedPlayhead);
1170
1154
  if (currentVod.sequenceAlwaysContainNewSegments) {
1171
1155
  mediaSequenceValue = currentVod.mediaSequenceValues[playheadState.vodMediaSeqVideo];
@@ -1182,23 +1166,23 @@ var Session = /** @class */ (function () {
1182
1166
  debug("[".concat(this._sessionId, "]: Session can now serve mseq[V]={").concat(playheadState.mediaSeq + mediaSequenceValue, "}") + audioInfo + subsInfo);
1183
1167
  }
1184
1168
  debug("[".concat(this._sessionId, "]: INCREMENT (mseq=").concat(playheadState.mediaSeq + playheadState.vodMediaSeqVideo, ") vodMediaSeq=(").concat(playheadState.vodMediaSeqVideo, "_").concat(playheadState.vodMediaSeqAudio).concat(this.use_vtt_subtitles ? "_".concat(playheadState.vodMediaSeqSubtitle) : "", " of ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio")).concat(this.use_vtt_subtitles ? "_".concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")") : ")"));
1185
- if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 34];
1169
+ if (!(playheadState.vodMediaSeqVideo < 2 || playheadState.mediaSeq !== this.prevMediaSeqOffset.video)) return [3 /*break*/, 23];
1186
1170
  debug("[".concat(this._sessionId, "]: current[").concat(playheadState.vodMediaSeqVideo, "]_prev[").concat(this.prevVodMediaSeq.video, "]"));
1187
1171
  debug("[".concat(this._sessionId, "]: current-offset[").concat(playheadState.mediaSeq, "]_prev-offset[").concat(this.prevMediaSeqOffset.video, "]"));
1188
1172
  if (playheadState.vodMediaSeqVideo < this.prevVodMediaSeq.video || playheadState.mediaSeq !== this.prevMediaSeqOffset.video) {
1189
1173
  this.isAllowedToClearVodCache = true;
1190
1174
  }
1191
- if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 33];
1175
+ if (!(!isLeader && this.isAllowedToClearVodCache)) return [3 /*break*/, 22];
1192
1176
  debug("[".concat(this._sessionId, "]: Not a leader and have just set 'playheadState.vodMediaSeqVideo' to 0|1. Invalidate cache to ensure having the correct VOD."));
1193
1177
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1194
- case 30:
1195
- _g.sent();
1178
+ case 19:
1179
+ _e.sent();
1196
1180
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1197
- case 31:
1198
- currentVod = _g.sent();
1181
+ case 20:
1182
+ currentVod = _e.sent();
1199
1183
  return [4 /*yield*/, this._playheadState.get("diffCompensation")];
1200
- case 32:
1201
- diffMs = _g.sent();
1184
+ case 21:
1185
+ diffMs = _e.sent();
1202
1186
  if (diffMs) {
1203
1187
  this.diffCompensation = diffMs;
1204
1188
  debug("[".concat(this._sessionId, "]: Setting diffCompensation->").concat(this.diffCompensation));
@@ -1211,12 +1195,12 @@ var Session = /** @class */ (function () {
1211
1195
  }
1212
1196
  }
1213
1197
  this.isAllowedToClearVodCache = false;
1214
- _g.label = 33;
1215
- case 33: return [3 /*break*/, 35];
1216
- case 34:
1198
+ _e.label = 22;
1199
+ case 22: return [3 /*break*/, 24];
1200
+ case 23:
1217
1201
  this.isAllowedToClearVodCache = true;
1218
- _g.label = 35;
1219
- case 35:
1202
+ _e.label = 24;
1203
+ case 24:
1220
1204
  // Update Value for Previous Sequence
1221
1205
  this.prevVodMediaSeq.video = playheadState.vodMediaSeqVideo;
1222
1206
  this.prevMediaSeqOffset.video = playheadState.mediaSeq;
@@ -1230,8 +1214,8 @@ var Session = /** @class */ (function () {
1230
1214
  }
1231
1215
  m3u8 = currentVod.getLiveMediaSequences(playheadState.mediaSeq, 180000, playheadState.vodMediaSeqVideo, sessionState.discSeq);
1232
1216
  return [4 /*yield*/, this._playheadState.setLastM3u8(m3u8)];
1233
- case 36:
1234
- _g.sent();
1217
+ case 25:
1218
+ _e.sent();
1235
1219
  return [2 /*return*/, m3u8];
1236
1220
  }
1237
1221
  });
@@ -1702,26 +1686,29 @@ var Session = /** @class */ (function () {
1702
1686
  if (!sessionState.state) {
1703
1687
  sessionState.state = SessionState.VOD_INIT;
1704
1688
  }
1689
+ _u.label = 4;
1690
+ case 4:
1691
+ _u.trys.push([4, , 106, 107]);
1705
1692
  _a = sessionState.state;
1706
1693
  switch (_a) {
1707
- case SessionState.VOD_INIT: return [3 /*break*/, 4];
1708
- case SessionState.VOD_INIT_BY_ID: return [3 /*break*/, 4];
1709
- case SessionState.VOD_PLAYING: return [3 /*break*/, 29];
1710
- case SessionState.VOD_NEXT_INITIATING: return [3 /*break*/, 35];
1711
- case SessionState.VOD_NEXT_INIT: return [3 /*break*/, 36];
1712
- case SessionState.VOD_RELOAD_INIT: return [3 /*break*/, 67];
1713
- case SessionState.VOD_RELOAD_INITIATING: return [3 /*break*/, 96];
1714
- }
1715
- return [3 /*break*/, 100];
1716
- case 4:
1717
- _u.trys.push([4, 26, , 29]);
1694
+ case SessionState.VOD_INIT: return [3 /*break*/, 5];
1695
+ case SessionState.VOD_INIT_BY_ID: return [3 /*break*/, 5];
1696
+ case SessionState.VOD_PLAYING: return [3 /*break*/, 31];
1697
+ case SessionState.VOD_NEXT_INITIATING: return [3 /*break*/, 37];
1698
+ case SessionState.VOD_NEXT_INIT: return [3 /*break*/, 38];
1699
+ case SessionState.VOD_RELOAD_INIT: return [3 /*break*/, 70];
1700
+ case SessionState.VOD_RELOAD_INITIATING: return [3 /*break*/, 100];
1701
+ }
1702
+ return [3 /*break*/, 104];
1703
+ case 5:
1704
+ _u.trys.push([5, 27, , 31]);
1718
1705
  // Needed if store was reset
1719
1706
  return [4 /*yield*/, this._sessionStateStore.clearLeaderCache()];
1720
- case 5:
1707
+ case 6:
1721
1708
  // Needed if store was reset
1722
1709
  _u.sent();
1723
1710
  return [4 /*yield*/, this._sessionStateStore.isLeader(this._instanceId)];
1724
- case 6:
1711
+ case 7:
1725
1712
  isLeader = _u.sent();
1726
1713
  nextVodPromise = void 0;
1727
1714
  if (sessionState.state === SessionState.VOD_INIT) {
@@ -1732,18 +1719,18 @@ var Session = /** @class */ (function () {
1732
1719
  debug("[".concat(this._sessionId, "]: state=VOD_INIT_BY_ID ").concat(sessionState.assetId));
1733
1720
  nextVodPromise = this._getNextVodById(sessionState.assetId);
1734
1721
  }
1735
- if (!isLeader) return [3 /*break*/, 22];
1722
+ if (!isLeader) return [3 /*break*/, 23];
1736
1723
  nextVodStart = Date.now();
1737
1724
  return [4 /*yield*/, nextVodPromise];
1738
- case 7:
1725
+ case 8:
1739
1726
  vodResponse = _u.sent();
1740
1727
  _b = sessionState;
1741
1728
  return [4 /*yield*/, this._sessionState.set("nextVod", vodResponse)];
1742
- case 8:
1729
+ case 9:
1743
1730
  _b.nextVod = _u.sent();
1744
1731
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'nextVod', channel: this._sessionId, reqTimeMs: Date.now() - nextVodStart });
1745
1732
  loadPromise = void 0;
1746
- if (!!vodResponse.type) return [3 /*break*/, 15];
1733
+ if (!!vodResponse.type) return [3 /*break*/, 16];
1747
1734
  debug("[".concat(this._sessionId, "]: got first VOD uri=").concat(vodResponse.uri, ":").concat(vodResponse.offset || 0));
1748
1735
  hlsOpts = {
1749
1736
  sequenceAlwaysContainNewSegments: this.alwaysNewSegments,
@@ -1763,40 +1750,40 @@ var Session = /** @class */ (function () {
1763
1750
  });
1764
1751
  }
1765
1752
  currentVod = newVod;
1766
- if (!vodResponse.desiredDuration) return [3 /*break*/, 13];
1767
- _u.label = 9;
1768
- case 9:
1769
- _u.trys.push([9, 11, , 12]);
1770
- return [4 /*yield*/, this._truncateVod(vodResponse)];
1753
+ if (!vodResponse.desiredDuration) return [3 /*break*/, 14];
1754
+ _u.label = 10;
1771
1755
  case 10:
1756
+ _u.trys.push([10, 12, , 13]);
1757
+ return [4 /*yield*/, this._truncateVod(vodResponse)];
1758
+ case 11:
1772
1759
  _c = _u.sent(), mediaManifestLoader = _c.mediaManifestLoader, audioManifestLoader = _c.audioManifestLoader, subtitleManifestLoader = _c.subtitleManifestLoader;
1773
1760
  loadPromise = currentVod.load(null, mediaManifestLoader, audioManifestLoader, subtitleManifestLoader);
1774
- return [3 /*break*/, 12];
1775
- case 11:
1761
+ return [3 /*break*/, 13];
1762
+ case 12:
1776
1763
  e_1 = _u.sent();
1777
1764
  console.error("[".concat(this._sessionId, "]: Failed to truncate VOD: ").concat(e_1));
1778
1765
  loadPromise = currentVod.load();
1779
- return [3 /*break*/, 12];
1780
- case 12: return [3 /*break*/, 14];
1781
- case 13:
1766
+ return [3 /*break*/, 13];
1767
+ case 13: return [3 /*break*/, 15];
1768
+ case 14:
1782
1769
  loadPromise = currentVod.load();
1783
- _u.label = 14;
1784
- case 14: return [3 /*break*/, 16];
1785
- case 15:
1770
+ _u.label = 15;
1771
+ case 15: return [3 /*break*/, 17];
1772
+ case 16:
1786
1773
  if (vodResponse.type === 'gap') {
1787
1774
  loadPromise = new Promise(function (resolve, reject) {
1788
- _this._fillGap(null, vodResponse.desiredDuration)
1775
+ _this._fillGap(null, vodResponse.desiredDuration, vodResponse.unixTs)
1789
1776
  .then(function (gapVod) {
1790
1777
  currentVod = gapVod;
1791
1778
  resolve(gapVod);
1792
1779
  }).catch(reject);
1793
1780
  });
1794
1781
  }
1795
- _u.label = 16;
1796
- case 16:
1782
+ _u.label = 17;
1783
+ case 17:
1797
1784
  loadStart = Date.now();
1798
1785
  return [4 /*yield*/, loadPromise];
1799
- case 17:
1786
+ case 18:
1800
1787
  _u.sent();
1801
1788
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'loadVod', channel: this._sessionId, loadTimeMs: Date.now() - loadStart });
1802
1789
  debug("[".concat(this._sessionId, "]: first VOD loaded. DeltaTimes ").concat(currentVod.getDeltaTimes().map(roundToThreeDecimals).join(",")));
@@ -1813,7 +1800,7 @@ var Session = /** @class */ (function () {
1813
1800
  "vodMediaSeqSubtitle": 0,
1814
1801
  "state": SessionState.VOD_PLAYING
1815
1802
  })];
1816
- case 18:
1803
+ case 19:
1817
1804
  updatedSessionState = _u.sent();
1818
1805
  sessionState = __assign(__assign({}, sessionState), updatedSessionState);
1819
1806
  this.produceEvent({
@@ -1825,29 +1812,29 @@ var Session = /** @class */ (function () {
1825
1812
  });
1826
1813
  _d = sessionState;
1827
1814
  return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 })];
1828
- case 19:
1815
+ case 20:
1829
1816
  _d.currentVod = _u.sent();
1830
1817
  _e = this;
1831
1818
  return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
1832
- case 20:
1819
+ case 21:
1833
1820
  _e.currentPlayheadRef = _u.sent();
1834
1821
  return [4 /*yield*/, this._sessionState.remove("nextVod")];
1835
- case 21:
1822
+ case 22:
1836
1823
  _u.sent();
1837
1824
  return [2 /*return*/];
1838
- case 22:
1825
+ case 23:
1839
1826
  debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_PLAYING"));
1840
1827
  _f = sessionState;
1841
1828
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_PLAYING)];
1842
- case 23:
1829
+ case 24:
1843
1830
  _f.state = _u.sent();
1844
1831
  _g = sessionState;
1845
1832
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1846
- case 24:
1833
+ case 25:
1847
1834
  _g.currentVod = _u.sent();
1848
1835
  return [2 /*return*/];
1849
- case 25: return [3 /*break*/, 29];
1850
- case 26:
1836
+ case 26: return [3 /*break*/, 31];
1837
+ case 27:
1851
1838
  err_5 = _u.sent();
1852
1839
  console.error("[".concat(this._sessionId, "]: Failed to init first VOD"));
1853
1840
  if (this._assetManager.handleError) {
@@ -1856,18 +1843,22 @@ var Session = /** @class */ (function () {
1856
1843
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'error', on: 'firstvod', channel: this._sessionId, err: err_5, vod: vodResponse });
1857
1844
  debug(err_5);
1858
1845
  return [4 /*yield*/, this._sessionState.remove("nextVod")];
1859
- case 27:
1846
+ case 28:
1860
1847
  _u.sent();
1861
1848
  return [4 /*yield*/, this._insertSlate(currentVod)];
1862
- case 28:
1849
+ case 29:
1863
1850
  currentVod = _u.sent();
1864
1851
  if (!currentVod) {
1865
1852
  debug("No slate to load");
1866
1853
  throw err_5;
1867
1854
  }
1868
- return [3 /*break*/, 29];
1869
- case 29:
1870
- if (!isLeader) return [3 /*break*/, 33];
1855
+ return [4 /*yield*/, this._sessionState.getValues(["state", "assetId", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "nextVod"])];
1856
+ case 30:
1857
+ // Re-read sessionState after _insertSlate modified it in Redis
1858
+ sessionState = _u.sent();
1859
+ return [3 /*break*/, 31];
1860
+ case 31:
1861
+ if (!isLeader) return [3 /*break*/, 35];
1871
1862
  // Handle edge case where store has been reset, but leader has not cleared cache.
1872
1863
  if (this.prevVodMediaSeq.video === null) {
1873
1864
  this.prevVodMediaSeq.video = sessionState.vodMediaSeqVideo;
@@ -1891,20 +1882,20 @@ var Session = /** @class */ (function () {
1891
1882
  this.prevMediaSeqOffset.subtitle = sessionState.mediaSeqSubtitle;
1892
1883
  }
1893
1884
  }
1894
- if (!(sessionState.vodMediaSeqVideo < this.prevVodMediaSeq.video)) return [3 /*break*/, 32];
1885
+ if (!(sessionState.vodMediaSeqVideo < this.prevVodMediaSeq.video)) return [3 /*break*/, 34];
1895
1886
  debug("[".concat(this._sessionId, "]: state=VOD_PLAYING, current[").concat(sessionState.vodMediaSeqVideo, "], prev[").concat(this.prevVodMediaSeq.video, "], total[").concat(currentVod.getLiveMediaSequencesCount(), "]"));
1896
1887
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
1897
- case 30:
1888
+ case 32:
1898
1889
  _u.sent();
1899
1890
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
1900
- case 31:
1891
+ case 33:
1901
1892
  currentVod = _u.sent();
1902
1893
  this.prevVodMediaSeq.video = sessionState.vodMediaSeqVideo;
1903
1894
  this.prevVodMediaSeq.audio = sessionState.vodMediaSeqAudio;
1904
1895
  this.prevVodMediaSeq.subtitle = sessionState.vodMediaSeqSubtitle;
1905
- _u.label = 32;
1906
- case 32: return [3 /*break*/, 34];
1907
- case 33:
1896
+ _u.label = 34;
1897
+ case 34: return [3 /*break*/, 36];
1898
+ case 35:
1908
1899
  // Handle edge case where Leader loaded next vod but Follower remained in state=VOD_PLAYING
1909
1900
  if ((this.prevMediaSeqOffset.video !== null) & (sessionState.mediaSeq !== this.prevMediaSeqOffset.video)) {
1910
1901
  debug("[".concat(this._sessionId, "]: state=VOD_PLAYING, current[").concat(sessionState.vodMediaSeqVideo, "], prev[").concat(this.prevVodMediaSeq.video, "], total[").concat(currentVod.getLiveMediaSequencesCount(), "]"));
@@ -1912,11 +1903,11 @@ var Session = /** @class */ (function () {
1912
1903
  // Allow Follower to clear VodCache...
1913
1904
  this.isAllowedToClearVodCache = true;
1914
1905
  }
1915
- _u.label = 34;
1916
- case 34:
1906
+ _u.label = 36;
1907
+ case 36:
1917
1908
  debug("[".concat(this._sessionId, "]: state=VOD_PLAYING (").concat(sessionState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqSubtitle, ", ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio"), "_").concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")"));
1918
1909
  return [2 /*return*/];
1919
- case 35:
1910
+ case 37:
1920
1911
  debug("[".concat(this._sessionId, "]: state=VOD_NEXT_INITIATING (").concat(sessionState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqSubtitle, ", ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio"), "_").concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")"));
1921
1912
  if (!isLeader) {
1922
1913
  debug("[".concat(this._sessionId, "]: not the leader so just waiting for the VOD to be initiated"));
@@ -1924,18 +1915,18 @@ var Session = /** @class */ (function () {
1924
1915
  // Allow Leader|Follower to clear vodCache...
1925
1916
  this.isAllowedToClearVodCache = true;
1926
1917
  return [2 /*return*/];
1927
- case 36:
1928
- _u.trys.push([36, 63, , 66]);
1918
+ case 38:
1919
+ _u.trys.push([38, 65, , 69]);
1929
1920
  debug("[".concat(this._sessionId, "]: state=VOD_NEXT_INIT"));
1930
- if (!isLeader) return [3 /*break*/, 58];
1931
- if (!!currentVod) return [3 /*break*/, 38];
1921
+ if (!isLeader) return [3 /*break*/, 60];
1922
+ if (!!currentVod) return [3 /*break*/, 40];
1932
1923
  debug("[".concat(this._sessionId, "]: no VOD to append to, assume first VOD to init"));
1933
1924
  _h = sessionState;
1934
1925
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_INIT)];
1935
- case 37:
1926
+ case 39:
1936
1927
  _h.state = _u.sent();
1937
1928
  return [2 /*return*/];
1938
- case 38:
1929
+ case 40:
1939
1930
  length_1 = currentVod.getLiveMediaSequencesCount();
1940
1931
  endMseqValue = void 0;
1941
1932
  endMseqValueAudio = void 0;
@@ -1955,28 +1946,28 @@ var Session = /** @class */ (function () {
1955
1946
  lastDiscontinuitySubtitle = currentVod.getLastDiscontinuitySubtitle();
1956
1947
  _j = sessionState;
1957
1948
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING)];
1958
- case 39:
1949
+ case 41:
1959
1950
  _j.state = _u.sent();
1960
1951
  vodPromise = this._getNextVod();
1961
- if (!(length_1 === 1)) return [3 /*break*/, 41];
1952
+ if (!(length_1 === 1)) return [3 /*break*/, 43];
1962
1953
  gracePeriod = (this.averageSegmentDuration / 2);
1963
1954
  debug("[".concat(this._sessionId, "]: adding a grace period before calling nextVod: ").concat(gracePeriod, "ms"));
1964
1955
  return [4 /*yield*/, timer(gracePeriod)];
1965
- case 40:
1956
+ case 42:
1966
1957
  _u.sent();
1967
- _u.label = 41;
1968
- case 41:
1958
+ _u.label = 43;
1959
+ case 43:
1969
1960
  nextVodStart = Date.now();
1970
1961
  return [4 /*yield*/, vodPromise];
1971
- case 42:
1962
+ case 44:
1972
1963
  vodResponse = _u.sent();
1973
1964
  _k = sessionState;
1974
1965
  return [4 /*yield*/, this._sessionState.set("nextVod", vodResponse)];
1975
- case 43:
1966
+ case 45:
1976
1967
  _k.nextVod = _u.sent();
1977
1968
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'nextVod', channel: this._sessionId, reqTimeMs: Date.now() - nextVodStart });
1978
1969
  loadPromise = void 0;
1979
- if (!!vodResponse.type) return [3 /*break*/, 50];
1970
+ if (!!vodResponse.type) return [3 /*break*/, 52];
1980
1971
  debug("[".concat(this._sessionId, "]: got next VOD uri=").concat(vodResponse.uri, ":").concat(vodResponse.offset));
1981
1972
  hlsOpts = {
1982
1973
  sequenceAlwaysContainNewSegments: this.alwaysNewSegments,
@@ -2003,25 +1994,25 @@ var Session = /** @class */ (function () {
2003
1994
  title: this.currentMetadata.title || '',
2004
1995
  }
2005
1996
  });
2006
- if (!vodResponse.desiredDuration) return [3 /*break*/, 48];
2007
- _u.label = 44;
2008
- case 44:
2009
- _u.trys.push([44, 46, , 47]);
1997
+ if (!vodResponse.desiredDuration) return [3 /*break*/, 50];
1998
+ _u.label = 46;
1999
+ case 46:
2000
+ _u.trys.push([46, 48, , 49]);
2010
2001
  return [4 /*yield*/, this._truncateVod(vodResponse)];
2011
- case 45:
2002
+ case 47:
2012
2003
  _l = _u.sent(), mediaManifestLoader = _l.mediaManifestLoader, audioManifestLoader = _l.audioManifestLoader, subtitleManifestLoader = _l.subtitleManifestLoader;
2013
2004
  loadPromise = newVod.loadAfter(currentVod, null, mediaManifestLoader, audioManifestLoader, subtitleManifestLoader);
2014
- return [3 /*break*/, 47];
2015
- case 46:
2005
+ return [3 /*break*/, 49];
2006
+ case 48:
2016
2007
  e_2 = _u.sent();
2017
2008
  console.error("[".concat(this._sessionId, "]: Failed to truncate VOD: ").concat(e_2));
2018
2009
  loadPromise = newVod.loadAfter(currentVod);
2019
- return [3 /*break*/, 47];
2020
- case 47: return [3 /*break*/, 49];
2021
- case 48:
2010
+ return [3 /*break*/, 49];
2011
+ case 49: return [3 /*break*/, 51];
2012
+ case 50:
2022
2013
  loadPromise = newVod.loadAfter(currentVod);
2023
- _u.label = 49;
2024
- case 49:
2014
+ _u.label = 51;
2015
+ case 51:
2025
2016
  if (vodResponse.diffMs) {
2026
2017
  this.diffCompensation = vodResponse.diffMs;
2027
2018
  if (this.diffCompensation) {
@@ -2032,20 +2023,20 @@ var Session = /** @class */ (function () {
2032
2023
  this.timePositionOffset = 0;
2033
2024
  }
2034
2025
  }
2035
- return [3 /*break*/, 51];
2036
- case 50:
2026
+ return [3 /*break*/, 53];
2027
+ case 52:
2037
2028
  loadPromise = new Promise(function (resolve, reject) {
2038
- _this._fillGap(currentVod, vodResponse.desiredDuration)
2029
+ _this._fillGap(currentVod, vodResponse.desiredDuration, vodResponse.unixTs)
2039
2030
  .then(function (gapVod) {
2040
2031
  newVod = gapVod;
2041
2032
  resolve(newVod);
2042
2033
  }).catch(reject);
2043
2034
  });
2044
- _u.label = 51;
2045
- case 51:
2035
+ _u.label = 53;
2036
+ case 53:
2046
2037
  loadStart = Date.now();
2047
2038
  return [4 /*yield*/, ChaosMonkey.loadVod(loadPromise)];
2048
- case 52:
2039
+ case 54:
2049
2040
  _u.sent();
2050
2041
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'loadVod', channel: this._sessionId, loadTimeMs: Date.now() - loadStart });
2051
2042
  this.leaderIsSettingNextVod = true;
@@ -2055,11 +2046,11 @@ var Session = /** @class */ (function () {
2055
2046
  debug("[".concat(this._sessionId, "]: msequences=").concat(currentVod.getLiveMediaSequencesCount(), "; audio msequences=").concat(currentVod.getLiveMediaSequencesCount("audio"), "; subtitle msequences=").concat(currentVod.getLiveMediaSequencesCount("subtitle")));
2056
2047
  _m = sessionState;
2057
2048
  return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod, { ttl: currentVod.getDuration() * 1000 })];
2058
- case 53:
2049
+ case 55:
2059
2050
  _m.currentVod = _u.sent();
2060
2051
  _o = this;
2061
2052
  return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
2062
- case 54:
2053
+ case 56:
2063
2054
  _o.currentPlayheadRef = _u.sent();
2064
2055
  return [4 /*yield*/, this._sessionState.setValues({
2065
2056
  "vodMediaSeqVideo": 0,
@@ -2072,16 +2063,16 @@ var Session = /** @class */ (function () {
2072
2063
  "discSeqAudio": sessionState.discSeqAudio + lastDiscontinuityAudio,
2073
2064
  "discSeqSubtitle": sessionState.discSeqSubtitle + lastDiscontinuitySubtitle
2074
2065
  })];
2075
- case 55:
2066
+ case 57:
2076
2067
  updatedSessionState = _u.sent();
2077
2068
  sessionState = __assign(__assign({}, sessionState), updatedSessionState);
2078
2069
  debug("[".concat(this._sessionId, "]: new sequence data set in store V[").concat(sessionState.mediaSeq, "][").concat(sessionState.discSeq, "]_A[").concat(sessionState.mediaSeqAudio, "][").concat(sessionState.discSeqAudio, "]_S[").concat(sessionState.mediaSeqSubtitle, "][").concat(sessionState.discSeqSubtitle, "]"));
2079
2070
  return [4 /*yield*/, this._sessionState.remove("nextVod")];
2080
- case 56:
2071
+ case 58:
2081
2072
  _u.sent();
2082
2073
  this.leaderIsSettingNextVod = false;
2083
2074
  return [4 /*yield*/, this._playheadState.set("diffCompensation", this.diffCompensation, isLeader)];
2084
- case 57:
2075
+ case 59:
2085
2076
  _u.sent();
2086
2077
  debug("[".concat(this._sessionId, "]: sharing current vods diffCompensation=").concat(this.diffCompensation));
2087
2078
  this.produceEvent({
@@ -2092,21 +2083,21 @@ var Session = /** @class */ (function () {
2092
2083
  }
2093
2084
  });
2094
2085
  return [2 /*return*/];
2095
- case 58:
2086
+ case 60:
2096
2087
  debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_NEXT_INITIATING"));
2097
2088
  this.waitingForNextVod = true;
2098
2089
  _p = sessionState;
2099
2090
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_NEXT_INITIATING)];
2100
- case 59:
2091
+ case 61:
2101
2092
  _p.state = _u.sent();
2102
2093
  // Allow Leader|Follower to clear vodCache...
2103
2094
  this.isAllowedToClearVodCache = true;
2104
2095
  _q = sessionState;
2105
2096
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
2106
- case 60:
2097
+ case 62:
2107
2098
  _q.currentVod = _u.sent();
2108
2099
  return [4 /*yield*/, this._playheadState.get("diffCompensation")];
2109
- case 61:
2100
+ case 63:
2110
2101
  diffMs = _u.sent();
2111
2102
  if (diffMs) {
2112
2103
  this.diffCompensation = diffMs;
@@ -2119,9 +2110,9 @@ var Session = /** @class */ (function () {
2119
2110
  this.timePositionOffset = 0;
2120
2111
  }
2121
2112
  }
2122
- _u.label = 62;
2123
- case 62: return [3 /*break*/, 66];
2124
- case 63:
2113
+ _u.label = 64;
2114
+ case 64: return [3 /*break*/, 69];
2115
+ case 65:
2125
2116
  err_6 = _u.sent();
2126
2117
  console.error("[".concat(this._sessionId, "]: Failed to init next VOD"));
2127
2118
  debug("[".concat(this._sessionId, "]: ").concat(err_6));
@@ -2130,31 +2121,35 @@ var Session = /** @class */ (function () {
2130
2121
  }
2131
2122
  cloudWatchLog(!this.cloudWatchLogging, 'engine-session', { event: 'error', on: 'nextvod', channel: this._sessionId, err: err_6, vod: vodResponse });
2132
2123
  return [4 /*yield*/, this._sessionState.remove("nextVod")];
2133
- case 64:
2124
+ case 66:
2134
2125
  _u.sent();
2135
2126
  return [4 /*yield*/, this._insertSlate(currentVod)];
2136
- case 65:
2127
+ case 67:
2137
2128
  currentVod = _u.sent();
2138
2129
  if (!currentVod) {
2139
2130
  debug("No slate to load");
2140
2131
  throw err_6;
2141
2132
  }
2133
+ return [4 /*yield*/, this._sessionState.getValues(["state", "assetId", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "nextVod"])];
2134
+ case 68:
2135
+ // Re-read sessionState after _insertSlate modified it in Redis
2136
+ sessionState = _u.sent();
2142
2137
  // Allow Leader|Follower to clear vodCache...
2143
2138
  this.isAllowedToClearVodCache = true;
2144
- return [3 /*break*/, 66];
2145
- case 66: return [3 /*break*/, 101];
2146
- case 67:
2147
- _u.trys.push([67, 94, , 95]);
2139
+ return [3 /*break*/, 69];
2140
+ case 69: return [3 /*break*/, 105];
2141
+ case 70:
2142
+ _u.trys.push([70, 98, , 99]);
2148
2143
  debug("[".concat(this._sessionId, "]: state=VOD_RELOAD_INIT"));
2149
2144
  if (this.diffCompensation <= 0) {
2150
2145
  this.diffCompensation = 0.1;
2151
2146
  }
2152
- if (!isLeader) return [3 /*break*/, 91];
2147
+ if (!isLeader) return [3 /*break*/, 95];
2153
2148
  startTS = Date.now();
2154
2149
  // 1) To tell Follower that, Leader is working on it!
2155
2150
  _r = sessionState;
2156
2151
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_RELOAD_INITIATING)];
2157
- case 68:
2152
+ case 71:
2158
2153
  // 1) To tell Follower that, Leader is working on it!
2159
2154
  _r.state = _u.sent();
2160
2155
  mseqV_1 = this.switchDataForSession.mediaSeq;
@@ -2162,7 +2157,7 @@ var Session = /** @class */ (function () {
2162
2157
  discSeqV_1 = this.switchDataForSession.discSeq;
2163
2158
  discSeqA = this.switchDataForSession.discAudioSeq;
2164
2159
  return [4 /*yield*/, this._sessionState.getCurrentVod()];
2165
- case 69:
2160
+ case 72:
2166
2161
  currentVod_1 = _u.sent();
2167
2162
  if (currentVod_1.sequenceAlwaysContainNewSegments) {
2168
2163
  // (!) will need to compensate if using this setting on HLSVod Object.
@@ -2217,87 +2212,87 @@ var Session = /** @class */ (function () {
2217
2212
  return [2 /*return*/];
2218
2213
  }
2219
2214
  return [4 /*yield*/, this._sessionState.set("mediaSeq", mseqV_1)];
2220
- case 70:
2215
+ case 73:
2221
2216
  _u.sent();
2222
2217
  return [4 /*yield*/, this._playheadState.set("mediaSeq", mseqV_1, isLeader)];
2223
- case 71:
2218
+ case 74:
2224
2219
  _u.sent();
2225
2220
  return [4 /*yield*/, this._sessionState.set("discSeq", discSeqV_1)];
2226
- case 72:
2221
+ case 75:
2227
2222
  _u.sent();
2228
2223
  // TODO: support demux^
2229
2224
  debug("[".concat(this._sessionId, "]: Setting current media and discontinuity count -> [").concat(mseqV_1, "]:[").concat(discSeqV_1, "]"));
2230
- if (!this.use_demuxed_audio) return [3 /*break*/, 76];
2225
+ if (!this.use_demuxed_audio) return [3 /*break*/, 79];
2231
2226
  return [4 /*yield*/, this._sessionState.set("mediaSeqAudio", mseqA)];
2232
- case 73:
2227
+ case 76:
2233
2228
  _u.sent();
2234
2229
  return [4 /*yield*/, this._playheadState.set("mediaSeqAudio", mseqA, isLeader)];
2235
- case 74:
2230
+ case 77:
2236
2231
  _u.sent();
2237
2232
  return [4 /*yield*/, this._sessionState.set("discSeqAudio", discSeqA)];
2238
- case 75:
2233
+ case 78:
2239
2234
  _u.sent();
2240
2235
  debug("[".concat(this._sessionId, "]: Setting current audio media and discontinuity count -> [").concat(mseqA, "]:[").concat(discSeqA, "]"));
2241
- _u.label = 76;
2242
- case 76:
2236
+ _u.label = 79;
2237
+ case 79:
2243
2238
  // 3) Set new media segments/currentVod, to carry on the continuity from session-live
2244
2239
  debug("[".concat(this._sessionId, "]: LEADER: making changes to current VOD. I will also update currentVod in store."));
2245
2240
  return [4 /*yield*/, this._playheadState.getValues(["vodMediaSeqVideo"])];
2246
- case 77:
2241
+ case 80:
2247
2242
  playheadState = _u.sent();
2248
2243
  nextMseq = playheadState.vodMediaSeqVideo + 1;
2249
2244
  if (nextMseq > currentVod_1.getLiveMediaSequencesCount() - 1) {
2250
2245
  nextMseq = currentVod_1.getLiveMediaSequencesCount() - 1;
2251
2246
  }
2252
- if (!this.use_demuxed_audio) return [3 /*break*/, 79];
2247
+ if (!this.use_demuxed_audio) return [3 /*break*/, 82];
2253
2248
  return [4 /*yield*/, this._playheadState.getValues(["vodMediaSeqAudio"])];
2254
- case 78:
2249
+ case 81:
2255
2250
  playheadStateAudio = _u.sent();
2256
2251
  nextAudioMseq = playheadStateAudio.vodMediaSeqAudio + 1;
2257
2252
  if (nextAudioMseq > currentVod_1.getLiveMediaSequencesCount("audio") - 1) {
2258
2253
  nextAudioMseq = currentVod_1.getLiveMediaSequencesCount("audio") - 1;
2259
2254
  }
2260
- _u.label = 79;
2261
- case 79:
2255
+ _u.label = 82;
2256
+ case 82:
2262
2257
  // ---------------------------------------------------.
2263
2258
  // TODO: Support reloading with SubtitleSegments as well |
2264
2259
  // ---------------------------------------------------'
2265
2260
  return [4 /*yield*/, currentVod_1.reload(nextMseq, segments, audioSegments, reloadBehind)];
2266
- case 80:
2261
+ case 83:
2267
2262
  // ---------------------------------------------------.
2268
2263
  // TODO: Support reloading with SubtitleSegments as well |
2269
2264
  // ---------------------------------------------------'
2270
2265
  _u.sent();
2271
2266
  return [4 /*yield*/, this._sessionState.setCurrentVod(currentVod_1, { ttl: currentVod_1.getDuration() * 1000 })];
2272
- case 81:
2267
+ case 84:
2273
2268
  _u.sent();
2274
2269
  return [4 /*yield*/, this._sessionState.set("vodReloaded", 1)];
2275
- case 82:
2270
+ case 85:
2276
2271
  _u.sent();
2277
2272
  return [4 /*yield*/, this._sessionState.set("vodMediaSeqVideo", 0)];
2278
- case 83:
2273
+ case 86:
2279
2274
  _u.sent();
2280
2275
  return [4 /*yield*/, this._playheadState.set("vodMediaSeqVideo", 0, isLeader)];
2281
- case 84:
2276
+ case 87:
2282
2277
  _u.sent();
2283
- if (!this.use_demuxed_audio) return [3 /*break*/, 89];
2278
+ if (!this.use_demuxed_audio) return [3 /*break*/, 92];
2284
2279
  return [4 /*yield*/, this._sessionState.set("vodMediaSeqAudio", 0)];
2285
- case 85:
2280
+ case 88:
2286
2281
  _u.sent();
2287
2282
  return [4 /*yield*/, this._playheadState.set("vodMediaSeqAudio", 0, isLeader)];
2288
- case 86:
2283
+ case 89:
2289
2284
  _u.sent();
2290
2285
  return [4 /*yield*/, this._sessionState.set("vodMediaSeqSubtitle", 0)];
2291
- case 87:
2286
+ case 90:
2292
2287
  _u.sent();
2293
2288
  return [4 /*yield*/, this._playheadState.set("vodMediaSeqSubtitle", 0, isLeader)];
2294
- case 88:
2289
+ case 91:
2295
2290
  _u.sent();
2296
- _u.label = 89;
2297
- case 89:
2291
+ _u.label = 92;
2292
+ case 92:
2298
2293
  _s = this;
2299
2294
  return [4 /*yield*/, this._playheadState.set("playheadRef", Date.now(), isLeader)];
2300
- case 90:
2295
+ case 93:
2301
2296
  _s.currentPlayheadRef = _u.sent();
2302
2297
  // 4) Log to debug and cloudwatch
2303
2298
  debug("[".concat(this._sessionId, "]: LEADER: Set new Reloaded VOD and vodMediaSeq counts in store."));
@@ -2313,39 +2308,48 @@ var Session = /** @class */ (function () {
2313
2308
  channel: this._sessionId,
2314
2309
  reqTimeMs: Date.now() - startTS,
2315
2310
  });
2311
+ return [4 /*yield*/, this._sessionState.getValues(["state", "assetId", "vodMediaSeqVideo", "vodMediaSeqAudio", "vodMediaSeqSubtitle", "mediaSeq", "mediaSeqAudio", "mediaSeqSubtitle", "discSeq", "discSeqAudio", "discSeqSubtitle", "nextVod"])];
2312
+ case 94:
2313
+ // Re-read sessionState after individual set() calls modified it in Redis
2314
+ sessionState = _u.sent();
2316
2315
  return [2 /*return*/];
2317
- case 91:
2316
+ case 95:
2318
2317
  debug("[".concat(this._sessionId, "]: not a leader so will go directly to state VOD_RELOAD_INITIATING"));
2319
2318
  _t = sessionState;
2320
2319
  return [4 /*yield*/, this._sessionState.set("state", SessionState.VOD_RELOAD_INITIATING)];
2321
- case 92:
2320
+ case 96:
2322
2321
  _t.state = _u.sent();
2323
- _u.label = 93;
2324
- case 93: return [3 /*break*/, 95];
2325
- case 94:
2322
+ _u.label = 97;
2323
+ case 97: return [3 /*break*/, 99];
2324
+ case 98:
2326
2325
  err_7 = _u.sent();
2327
2326
  debug("Failed to init reload vod");
2328
2327
  throw err_7;
2329
- case 95: return [3 /*break*/, 101];
2330
- case 96:
2328
+ case 99: return [3 /*break*/, 105];
2329
+ case 100:
2331
2330
  debug("[".concat(this._sessionId, "]: state=VOD_RELOAD_INITIATING (").concat(sessionState.vodMediaSeqVideo, "_").concat(sessionState.vodMediaSeqAudio, "_").concat(sessionState.vodMediaSeqSubtitle, ", ").concat(currentVod.getLiveMediaSequencesCount(), "_").concat(currentVod.getLiveMediaSequencesCount("audio"), "_").concat(currentVod.getLiveMediaSequencesCount("subtitle"), ")"));
2332
- if (!!isLeader) return [3 /*break*/, 99];
2331
+ if (!!isLeader) return [3 /*break*/, 103];
2333
2332
  debug("[".concat(this._sessionId, "]: not the leader so just waiting for the VOD to be reloaded"));
2334
- if (!(sessionState.vodMediaSeqVideo === 0 || this.waitingForNextVod)) return [3 /*break*/, 98];
2333
+ if (!(sessionState.vodMediaSeqVideo === 0 || this.waitingForNextVod)) return [3 /*break*/, 102];
2335
2334
  debug("[".concat(this._sessionId, "]: First mediasequence in VOD and I am not the leader so invalidate current VOD cache and fetch the new one from the leader"));
2336
2335
  return [4 /*yield*/, this._sessionState.clearCurrentVodCache()];
2337
- case 97:
2336
+ case 101:
2338
2337
  _u.sent();
2339
- _u.label = 98;
2340
- case 98:
2338
+ _u.label = 102;
2339
+ case 102:
2341
2340
  this.waitingForNextVod = true;
2342
- _u.label = 99;
2343
- case 99:
2341
+ _u.label = 103;
2342
+ case 103:
2344
2343
  // Allow Leader|Follower to clear vodCache...
2345
2344
  this.isAllowedToClearVodCache = true;
2346
2345
  return [2 /*return*/];
2347
- case 100: throw new Error("Invalid state: " + sessionState.state);
2348
- case 101: return [2 /*return*/];
2346
+ case 104: throw new Error("Invalid state: " + sessionState.state);
2347
+ case 105: return [3 /*break*/, 107];
2348
+ case 106:
2349
+ // Store tick state for incrementAsync to reuse, avoiding redundant Redis reads
2350
+ this._lastTickState = { sessionState: sessionState, isLeader: isLeader, currentVod: currentVod };
2351
+ return [7 /*endfinally*/];
2352
+ case 107: return [2 /*return*/];
2349
2353
  }
2350
2354
  });
2351
2355
  });
@@ -2382,7 +2386,7 @@ var Session = /** @class */ (function () {
2382
2386
  .catch(reject);
2383
2387
  });
2384
2388
  };
2385
- Session.prototype._loadSlate = function (afterVod, reps) {
2389
+ Session.prototype._loadSlate = function (afterVod, reps, unixTs) {
2386
2390
  var _this = this;
2387
2391
  return new Promise(function (resolve, reject) {
2388
2392
  try {
@@ -2401,7 +2405,7 @@ var Session = /** @class */ (function () {
2401
2405
  skipSerializeMediaSequences: _this.partialStoreHLSVod,
2402
2406
  calculatePDT: _this.rollingPDT
2403
2407
  };
2404
- var timestamp = Date.now();
2408
+ var timestamp = unixTs ? unixTs : Date.now();
2405
2409
  hlsVod_1 = new HLSVod(_this.slateUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
2406
2410
  hlsVod_1.addMetadata('id', "slate-".concat(timestamp));
2407
2411
  hlsVod_1.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -2503,7 +2507,7 @@ var Session = /** @class */ (function () {
2503
2507
  }
2504
2508
  });
2505
2509
  };
2506
- Session.prototype._truncateSlate = function (afterVod, requestedDuration, vodUri) {
2510
+ Session.prototype._truncateSlate = function (afterVod, requestedDuration, vodUri, unixTs) {
2507
2511
  var _this = this;
2508
2512
  return new Promise(function (resolve, reject) {
2509
2513
  var nexVodUri = null;
@@ -2529,7 +2533,7 @@ var Session = /** @class */ (function () {
2529
2533
  skipSerializeMediaSequences: _this.partialStoreHLSVod,
2530
2534
  calculatePDT: _this.rollingPDT
2531
2535
  };
2532
- var timestamp = Date.now();
2536
+ var timestamp = unixTs ? unixTs : Date.now();
2533
2537
  hlsVod_2 = new HLSVod(nexVodUri, null, timestamp, null, m3u8Header(_this._instanceId), hlsOpts);
2534
2538
  hlsVod_2.addMetadata('id', "slate-".concat(timestamp));
2535
2539
  hlsVod_2.addMetadata('start-date', new Date(timestamp).toISOString());
@@ -2586,7 +2590,7 @@ var Session = /** @class */ (function () {
2586
2590
  }
2587
2591
  });
2588
2592
  };
2589
- Session.prototype._fillGap = function (afterVod, desiredDuration) {
2593
+ Session.prototype._fillGap = function (afterVod, desiredDuration, unixTs) {
2590
2594
  var _this = this;
2591
2595
  return new Promise(function (resolve, reject) {
2592
2596
  var loadSlatePromise;
@@ -2594,12 +2598,12 @@ var Session = /** @class */ (function () {
2594
2598
  if (desiredDuration > _this.slateDuration) {
2595
2599
  var reps = Math.floor(desiredDuration / _this.slateDuration);
2596
2600
  debug("[".concat(_this._sessionId, "]: Trying to fill a gap of ").concat(desiredDuration, " milliseconds (").concat(reps, " repetitions)"));
2597
- loadSlatePromise = _this._loadSlate(afterVod, reps);
2601
+ loadSlatePromise = _this._loadSlate(afterVod, reps, unixTs);
2598
2602
  durationMs = (reps || _this.slateRepetitions) * _this.slateDuration;
2599
2603
  }
2600
2604
  else {
2601
2605
  debug("[".concat(_this._sessionId, "]: Trying to fill a gap of ").concat(desiredDuration, " milliseconds by truncating filler slate (").concat(_this.slateDuration, ")"));
2602
- loadSlatePromise = _this._truncateSlate(afterVod, desiredDuration / 1000);
2606
+ loadSlatePromise = _this._truncateSlate(afterVod, desiredDuration / 1000, null, unixTs);
2603
2607
  durationMs = desiredDuration;
2604
2608
  }
2605
2609
  loadSlatePromise.then(function (hlsVod) {