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.js CHANGED
@@ -1893,8 +1893,17 @@ function buildPlayerTopic(licenseKey, channel) {
1893
1893
  // src/utils/mqttClient.ts
1894
1894
  import mqtt from "mqtt";
1895
1895
  var LOG = "[StormcloudVideoPlayer][MQTT]";
1896
+ var KEEPALIVE_SECONDS = 30;
1897
+ var CONNECT_TIMEOUT_MS = 1e4;
1898
+ var RECONNECT_BASE_MS = 5e3;
1899
+ var RECONNECT_MAX_MS = 6e4;
1900
+ var MAX_RECONNECT_ATTEMPTS = 8;
1901
+ var COOLDOWN_MS = 10 * 6e4;
1896
1902
  var client = null;
1897
1903
  var status = "disconnected";
1904
+ var reconnectAttempts = 0;
1905
+ var reconnectTimer = null;
1906
+ var stopped = false;
1898
1907
  function getMQTTStatus() {
1899
1908
  return status;
1900
1909
  }
@@ -1908,8 +1917,45 @@ function configureMQTT(overrides) {
1908
1917
  applyMQTTConfig(overrides);
1909
1918
  disconnectMQTT();
1910
1919
  }
1911
- function initMQTTClient() {
1912
- if (client || !isMQTTEnabled()) return;
1920
+ function clearReconnectTimer() {
1921
+ if (reconnectTimer) {
1922
+ clearTimeout(reconnectTimer);
1923
+ reconnectTimer = null;
1924
+ }
1925
+ }
1926
+ function teardownClient() {
1927
+ if (client) {
1928
+ try {
1929
+ client.removeAllListeners();
1930
+ client.end(true);
1931
+ } catch (unused) {}
1932
+ client = null;
1933
+ }
1934
+ }
1935
+ function scheduleReconnect() {
1936
+ if (stopped || !isMQTTEnabled() || reconnectTimer) return;
1937
+ if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
1938
+ console.warn("".concat(LOG, " giving up after ").concat(reconnectAttempts, " attempts; cooling down for ").concat(COOLDOWN_MS / 6e4, "m"));
1939
+ teardownClient();
1940
+ status = "disconnected";
1941
+ reconnectTimer = setTimeout(function() {
1942
+ reconnectTimer = null;
1943
+ reconnectAttempts = 0;
1944
+ openConnection();
1945
+ }, COOLDOWN_MS);
1946
+ return;
1947
+ }
1948
+ var delay = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * Math.pow(2, reconnectAttempts));
1949
+ var jitter = Math.floor(Math.random() * 1e3);
1950
+ reconnectAttempts += 1;
1951
+ reconnectTimer = setTimeout(function() {
1952
+ reconnectTimer = null;
1953
+ openConnection();
1954
+ }, delay + jitter);
1955
+ }
1956
+ function openConnection() {
1957
+ if (stopped || !isMQTTEnabled()) return;
1958
+ teardownClient();
1913
1959
  var url = buildMQTTBrokerUrl();
1914
1960
  status = "connecting";
1915
1961
  var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
@@ -1918,41 +1964,57 @@ function initMQTTClient() {
1918
1964
  clientId: clientId,
1919
1965
  username: mqttConfig.username,
1920
1966
  password: mqttConfig.password,
1921
- keepalive: 60,
1967
+ keepalive: KEEPALIVE_SECONDS,
1922
1968
  clean: true,
1923
- reconnectPeriod: 5e3,
1924
- connectTimeout: 1e4,
1925
- queueQoSZero: false
1969
+ // Disable MQTT.js internal reconnect; we manage reconnection ourselves.
1970
+ reconnectPeriod: 0,
1971
+ connectTimeout: CONNECT_TIMEOUT_MS,
1972
+ queueQoSZero: false,
1973
+ reschedulePings: true,
1974
+ // Root-cause fix for the Tizen 4.0 "Keepalive timeout" loop: MQTT.js's
1975
+ // default timerVariant "auto" runs the keepalive interval inside a
1976
+ // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old
1977
+ // WebKit) served from a file:// origin that worker can't tick reliably,
1978
+ // so the keepalive counter trips onKeepaliveTimeout almost immediately
1979
+ // after connect. Force the native setInterval timer instead; the main
1980
+ // thread is free because video is decoded by the native AVPlay pipeline.
1981
+ timerVariant: "native"
1926
1982
  });
1927
1983
  } catch (err) {
1928
1984
  status = "error";
1929
1985
  console.warn("".concat(LOG, " connect() threw:"), err);
1986
+ scheduleReconnect();
1930
1987
  return;
1931
1988
  }
1932
1989
  client.on("connect", function() {
1933
1990
  status = "connected";
1991
+ reconnectAttempts = 0;
1992
+ clearReconnectTimer();
1934
1993
  console.info("".concat(LOG, " connected to ").concat(url));
1935
1994
  });
1936
- client.on("reconnect", function() {
1937
- status = "connecting";
1938
- console.info("".concat(LOG, " reconnecting…"));
1939
- });
1940
1995
  client.on("offline", function() {
1941
- status = "disconnected";
1996
+ if (status === "connected") status = "disconnected";
1942
1997
  console.warn("".concat(LOG, " offline"));
1998
+ scheduleReconnect();
1943
1999
  });
1944
2000
  client.on("error", function(err) {
1945
2001
  status = "error";
1946
2002
  console.warn("".concat(LOG, " error:"), err.message);
2003
+ scheduleReconnect();
1947
2004
  });
1948
2005
  client.on("close", function() {
1949
- if (status === "connected") {
1950
- status = "disconnected";
1951
- }
2006
+ if (status === "connected") status = "disconnected";
2007
+ scheduleReconnect();
1952
2008
  });
1953
2009
  }
2010
+ function initMQTTClient() {
2011
+ if (client || !isMQTTEnabled()) return;
2012
+ stopped = false;
2013
+ reconnectAttempts = 0;
2014
+ openConnection();
2015
+ }
1954
2016
  function ensureMQTTClient() {
1955
- if (isMQTTEnabled() && !client) {
2017
+ if (isMQTTEnabled() && !client && !reconnectTimer) {
1956
2018
  initMQTTClient();
1957
2019
  }
1958
2020
  }
@@ -1961,7 +2023,7 @@ function publishMQTT(topic, payload) {
1961
2023
  return false;
1962
2024
  }
1963
2025
  ensureMQTTClient();
1964
- if (!client) {
2026
+ if (!client || !client.connected) {
1965
2027
  return false;
1966
2028
  }
1967
2029
  try {
@@ -1975,11 +2037,11 @@ function publishMQTT(topic, payload) {
1975
2037
  }
1976
2038
  }
1977
2039
  function disconnectMQTT() {
1978
- if (client) {
1979
- client.end(true);
1980
- client = null;
1981
- status = "disconnected";
1982
- }
2040
+ stopped = true;
2041
+ clearReconnectTimer();
2042
+ teardownClient();
2043
+ reconnectAttempts = 0;
2044
+ status = "disconnected";
1983
2045
  }
1984
2046
  // src/utils/vastEnvironmentSignals.ts
1985
2047
  var AIRY_ANDROID_APP_ID = "com.freeairytv.android";