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