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.
@@ -1958,10 +1958,56 @@ function buildPlayerTopic(licenseKey, channel) {
1958
1958
  // src/utils/mqttClient.ts
1959
1959
  var import_mqtt = __toESM(require("mqtt"), 1);
1960
1960
  var LOG = "[StormcloudVideoPlayer][MQTT]";
1961
+ var KEEPALIVE_SECONDS = 30;
1962
+ var CONNECT_TIMEOUT_MS = 1e4;
1963
+ var RECONNECT_BASE_MS = 5e3;
1964
+ var RECONNECT_MAX_MS = 6e4;
1965
+ var MAX_RECONNECT_ATTEMPTS = 8;
1966
+ var COOLDOWN_MS = 10 * 6e4;
1961
1967
  var client = null;
1962
1968
  var status = "disconnected";
1963
- function initMQTTClient() {
1964
- if (client || !isMQTTEnabled()) return;
1969
+ var reconnectAttempts = 0;
1970
+ var reconnectTimer = null;
1971
+ var stopped = false;
1972
+ function clearReconnectTimer() {
1973
+ if (reconnectTimer) {
1974
+ clearTimeout(reconnectTimer);
1975
+ reconnectTimer = null;
1976
+ }
1977
+ }
1978
+ function teardownClient() {
1979
+ if (client) {
1980
+ try {
1981
+ client.removeAllListeners();
1982
+ client.end(true);
1983
+ } catch (unused) {}
1984
+ client = null;
1985
+ }
1986
+ }
1987
+ function scheduleReconnect() {
1988
+ if (stopped || !isMQTTEnabled() || reconnectTimer) return;
1989
+ if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
1990
+ console.warn("".concat(LOG, " giving up after ").concat(reconnectAttempts, " attempts; cooling down for ").concat(COOLDOWN_MS / 6e4, "m"));
1991
+ teardownClient();
1992
+ status = "disconnected";
1993
+ reconnectTimer = setTimeout(function() {
1994
+ reconnectTimer = null;
1995
+ reconnectAttempts = 0;
1996
+ openConnection();
1997
+ }, COOLDOWN_MS);
1998
+ return;
1999
+ }
2000
+ var delay = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * Math.pow(2, reconnectAttempts));
2001
+ var jitter = Math.floor(Math.random() * 1e3);
2002
+ reconnectAttempts += 1;
2003
+ reconnectTimer = setTimeout(function() {
2004
+ reconnectTimer = null;
2005
+ openConnection();
2006
+ }, delay + jitter);
2007
+ }
2008
+ function openConnection() {
2009
+ if (stopped || !isMQTTEnabled()) return;
2010
+ teardownClient();
1965
2011
  var url = buildMQTTBrokerUrl();
1966
2012
  status = "connecting";
1967
2013
  var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
@@ -1970,41 +2016,57 @@ function initMQTTClient() {
1970
2016
  clientId: clientId,
1971
2017
  username: mqttConfig.username,
1972
2018
  password: mqttConfig.password,
1973
- keepalive: 60,
2019
+ keepalive: KEEPALIVE_SECONDS,
1974
2020
  clean: true,
1975
- reconnectPeriod: 5e3,
1976
- connectTimeout: 1e4,
1977
- queueQoSZero: false
2021
+ // Disable MQTT.js internal reconnect; we manage reconnection ourselves.
2022
+ reconnectPeriod: 0,
2023
+ connectTimeout: CONNECT_TIMEOUT_MS,
2024
+ queueQoSZero: false,
2025
+ reschedulePings: true,
2026
+ // Root-cause fix for the Tizen 4.0 "Keepalive timeout" loop: MQTT.js's
2027
+ // default timerVariant "auto" runs the keepalive interval inside a
2028
+ // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old
2029
+ // WebKit) served from a file:// origin that worker can't tick reliably,
2030
+ // so the keepalive counter trips onKeepaliveTimeout almost immediately
2031
+ // after connect. Force the native setInterval timer instead; the main
2032
+ // thread is free because video is decoded by the native AVPlay pipeline.
2033
+ timerVariant: "native"
1978
2034
  });
1979
2035
  } catch (err) {
1980
2036
  status = "error";
1981
2037
  console.warn("".concat(LOG, " connect() threw:"), err);
2038
+ scheduleReconnect();
1982
2039
  return;
1983
2040
  }
1984
2041
  client.on("connect", function() {
1985
2042
  status = "connected";
2043
+ reconnectAttempts = 0;
2044
+ clearReconnectTimer();
1986
2045
  console.info("".concat(LOG, " connected to ").concat(url));
1987
2046
  });
1988
- client.on("reconnect", function() {
1989
- status = "connecting";
1990
- console.info("".concat(LOG, " reconnecting…"));
1991
- });
1992
2047
  client.on("offline", function() {
1993
- status = "disconnected";
2048
+ if (status === "connected") status = "disconnected";
1994
2049
  console.warn("".concat(LOG, " offline"));
2050
+ scheduleReconnect();
1995
2051
  });
1996
2052
  client.on("error", function(err) {
1997
2053
  status = "error";
1998
2054
  console.warn("".concat(LOG, " error:"), err.message);
2055
+ scheduleReconnect();
1999
2056
  });
2000
2057
  client.on("close", function() {
2001
- if (status === "connected") {
2002
- status = "disconnected";
2003
- }
2058
+ if (status === "connected") status = "disconnected";
2059
+ scheduleReconnect();
2004
2060
  });
2005
2061
  }
2062
+ function initMQTTClient() {
2063
+ if (client || !isMQTTEnabled()) return;
2064
+ stopped = false;
2065
+ reconnectAttempts = 0;
2066
+ openConnection();
2067
+ }
2006
2068
  function ensureMQTTClient() {
2007
- if (isMQTTEnabled() && !client) {
2069
+ if (isMQTTEnabled() && !client && !reconnectTimer) {
2008
2070
  initMQTTClient();
2009
2071
  }
2010
2072
  }
@@ -2013,7 +2075,7 @@ function publishMQTT(topic, payload) {
2013
2075
  return false;
2014
2076
  }
2015
2077
  ensureMQTTClient();
2016
- if (!client) {
2078
+ if (!client || !client.connected) {
2017
2079
  return false;
2018
2080
  }
2019
2081
  try {