stormcloud-video-player 0.8.38 → 0.8.40

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/lib/index.cjs CHANGED
@@ -2110,8 +2110,17 @@ function buildPlayerTopic(licenseKey, channel) {
2110
2110
  // src/utils/mqttClient.ts
2111
2111
  var import_mqtt = __toESM(require("mqtt"), 1);
2112
2112
  var LOG = "[StormcloudVideoPlayer][MQTT]";
2113
+ var KEEPALIVE_SECONDS = 30;
2114
+ var CONNECT_TIMEOUT_MS = 1e4;
2115
+ var RECONNECT_BASE_MS = 5e3;
2116
+ var RECONNECT_MAX_MS = 6e4;
2117
+ var MAX_RECONNECT_ATTEMPTS = 8;
2118
+ var COOLDOWN_MS = 10 * 6e4;
2113
2119
  var client = null;
2114
2120
  var status = "disconnected";
2121
+ var reconnectAttempts = 0;
2122
+ var reconnectTimer = null;
2123
+ var stopped = false;
2115
2124
  function getMQTTStatus() {
2116
2125
  return status;
2117
2126
  }
@@ -2125,8 +2134,45 @@ function configureMQTT(overrides) {
2125
2134
  applyMQTTConfig(overrides);
2126
2135
  disconnectMQTT();
2127
2136
  }
2128
- function initMQTTClient() {
2129
- if (client || !isMQTTEnabled()) return;
2137
+ function clearReconnectTimer() {
2138
+ if (reconnectTimer) {
2139
+ clearTimeout(reconnectTimer);
2140
+ reconnectTimer = null;
2141
+ }
2142
+ }
2143
+ function teardownClient() {
2144
+ if (client) {
2145
+ try {
2146
+ client.removeAllListeners();
2147
+ client.end(true);
2148
+ } catch (unused) {}
2149
+ client = null;
2150
+ }
2151
+ }
2152
+ function scheduleReconnect() {
2153
+ if (stopped || !isMQTTEnabled() || reconnectTimer) return;
2154
+ if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
2155
+ console.warn("".concat(LOG, " giving up after ").concat(reconnectAttempts, " attempts; cooling down for ").concat(COOLDOWN_MS / 6e4, "m"));
2156
+ teardownClient();
2157
+ status = "disconnected";
2158
+ reconnectTimer = setTimeout(function() {
2159
+ reconnectTimer = null;
2160
+ reconnectAttempts = 0;
2161
+ openConnection();
2162
+ }, COOLDOWN_MS);
2163
+ return;
2164
+ }
2165
+ var delay = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * Math.pow(2, reconnectAttempts));
2166
+ var jitter = Math.floor(Math.random() * 1e3);
2167
+ reconnectAttempts += 1;
2168
+ reconnectTimer = setTimeout(function() {
2169
+ reconnectTimer = null;
2170
+ openConnection();
2171
+ }, delay + jitter);
2172
+ }
2173
+ function openConnection() {
2174
+ if (stopped || !isMQTTEnabled()) return;
2175
+ teardownClient();
2130
2176
  var url = buildMQTTBrokerUrl();
2131
2177
  status = "connecting";
2132
2178
  var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
@@ -2135,41 +2181,57 @@ function initMQTTClient() {
2135
2181
  clientId: clientId,
2136
2182
  username: mqttConfig.username,
2137
2183
  password: mqttConfig.password,
2138
- keepalive: 60,
2184
+ keepalive: KEEPALIVE_SECONDS,
2139
2185
  clean: true,
2140
- reconnectPeriod: 5e3,
2141
- connectTimeout: 1e4,
2142
- queueQoSZero: false
2186
+ // Disable MQTT.js internal reconnect; we manage reconnection ourselves.
2187
+ reconnectPeriod: 0,
2188
+ connectTimeout: CONNECT_TIMEOUT_MS,
2189
+ queueQoSZero: false,
2190
+ reschedulePings: true,
2191
+ // Root-cause fix for the Tizen 4.0 "Keepalive timeout" loop: MQTT.js's
2192
+ // default timerVariant "auto" runs the keepalive interval inside a
2193
+ // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old
2194
+ // WebKit) served from a file:// origin that worker can't tick reliably,
2195
+ // so the keepalive counter trips onKeepaliveTimeout almost immediately
2196
+ // after connect. Force the native setInterval timer instead; the main
2197
+ // thread is free because video is decoded by the native AVPlay pipeline.
2198
+ timerVariant: "native"
2143
2199
  });
2144
2200
  } catch (err) {
2145
2201
  status = "error";
2146
2202
  console.warn("".concat(LOG, " connect() threw:"), err);
2203
+ scheduleReconnect();
2147
2204
  return;
2148
2205
  }
2149
2206
  client.on("connect", function() {
2150
2207
  status = "connected";
2208
+ reconnectAttempts = 0;
2209
+ clearReconnectTimer();
2151
2210
  console.info("".concat(LOG, " connected to ").concat(url));
2152
2211
  });
2153
- client.on("reconnect", function() {
2154
- status = "connecting";
2155
- console.info("".concat(LOG, " reconnecting…"));
2156
- });
2157
2212
  client.on("offline", function() {
2158
- status = "disconnected";
2213
+ if (status === "connected") status = "disconnected";
2159
2214
  console.warn("".concat(LOG, " offline"));
2215
+ scheduleReconnect();
2160
2216
  });
2161
2217
  client.on("error", function(err) {
2162
2218
  status = "error";
2163
2219
  console.warn("".concat(LOG, " error:"), err.message);
2220
+ scheduleReconnect();
2164
2221
  });
2165
2222
  client.on("close", function() {
2166
- if (status === "connected") {
2167
- status = "disconnected";
2168
- }
2223
+ if (status === "connected") status = "disconnected";
2224
+ scheduleReconnect();
2169
2225
  });
2170
2226
  }
2227
+ function initMQTTClient() {
2228
+ if (client || !isMQTTEnabled()) return;
2229
+ stopped = false;
2230
+ reconnectAttempts = 0;
2231
+ openConnection();
2232
+ }
2171
2233
  function ensureMQTTClient() {
2172
- if (isMQTTEnabled() && !client) {
2234
+ if (isMQTTEnabled() && !client && !reconnectTimer) {
2173
2235
  initMQTTClient();
2174
2236
  }
2175
2237
  }
@@ -2178,7 +2240,7 @@ function publishMQTT(topic, payload) {
2178
2240
  return false;
2179
2241
  }
2180
2242
  ensureMQTTClient();
2181
- if (!client) {
2243
+ if (!client || !client.connected) {
2182
2244
  return false;
2183
2245
  }
2184
2246
  try {
@@ -2192,11 +2254,11 @@ function publishMQTT(topic, payload) {
2192
2254
  }
2193
2255
  }
2194
2256
  function disconnectMQTT() {
2195
- if (client) {
2196
- client.end(true);
2197
- client = null;
2198
- status = "disconnected";
2199
- }
2257
+ stopped = true;
2258
+ clearReconnectTimer();
2259
+ teardownClient();
2260
+ reconnectAttempts = 0;
2261
+ status = "disconnected";
2200
2262
  }
2201
2263
  // src/utils/vastEnvironmentSignals.ts
2202
2264
  var AIRY_ANDROID_APP_ID = "com.freeairytv.android";