@camstack/addon-provider-dreame 0.2.73 → 0.2.75

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/dist/addon.js CHANGED
@@ -86331,6 +86331,53 @@ var BaseDeviceProvider = class extends BaseAddon {
86331
86331
  const ids = [...this._permanentRestoreFailures.keys()].join(", ");
86332
86332
  return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) — restart the ${this.providerName} provider to retry`;
86333
86333
  }
86334
+ /**
86335
+ * A top-level persisted row with NO configuration is a leftover, not a
86336
+ * device — quarantine it instead of dialling it.
86337
+ *
86338
+ * Device 614 was deleted, resurrected as a config-less shell by a write
86339
+ * already in flight (D376), and then dialled at every single boot: eight
86340
+ * `Failed to restore device — bounded retry scheduled` lines in one day,
86341
+ * each one the same Zod refusal on `host` and `password`. The bound was
86342
+ * real, but it is a bound PER PROCESS, and the runner restarts — so nothing
86343
+ * about the row ever stopped costing attempts and log lines.
86344
+ *
86345
+ * No retry can add a configuration that is not there. The row is reported
86346
+ * once, with its `deviceId`, and set aside.
86347
+ *
86348
+ * Top-level only: an accessory child legitimately carries an empty blob (it
86349
+ * lives off its parent), and a hub-adopted child with an emptied blob is
86350
+ * repaired by `healSavedConfig` from its parent instead. Providers that
86351
+ * genuinely create configuration-free top-level devices turn this off.
86352
+ */
86353
+ quarantineConfiglessTopLevelRestores = true;
86354
+ isUnrestorableShell(saved) {
86355
+ if (!this.quarantineConfiglessTopLevelRestores) return false;
86356
+ if (saved.parentDeviceId !== null) return false;
86357
+ const config = saved.config;
86358
+ if (config === void 0) return false;
86359
+ return Object.keys(config).length === 0;
86360
+ }
86361
+ quarantineShell(saved) {
86362
+ this._permanentRestoreFailures.set(saved.id, {
86363
+ deviceId: saved.id,
86364
+ stableId: saved.stableId,
86365
+ type: saved.type,
86366
+ attempts: 0,
86367
+ lastError: "persisted row has no configuration",
86368
+ failedAt: Date.now()
86369
+ });
86370
+ this.ctx.logger.error("Persisted device row has NO configuration — quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
86371
+ tags: {
86372
+ deviceId: saved.id,
86373
+ stableId: saved.stableId
86374
+ },
86375
+ meta: {
86376
+ type: saved.type,
86377
+ provider: this.providerName
86378
+ }
86379
+ });
86380
+ }
86334
86381
  cancelRestoreRetries() {
86335
86382
  this._restoreRetryScheduler?.cancel();
86336
86383
  this._restoreRetryScheduler = null;
@@ -86515,6 +86562,10 @@ var BaseDeviceProvider = class extends BaseAddon {
86515
86562
  });
86516
86563
  return;
86517
86564
  }
86565
+ if (this.isUnrestorableShell(saved)) {
86566
+ this.quarantineShell(saved);
86567
+ return;
86568
+ }
86518
86569
  try {
86519
86570
  await attemptRestore(saved);
86520
86571
  } catch (err) {
package/dist/addon.mjs CHANGED
@@ -86328,6 +86328,53 @@ var BaseDeviceProvider = class extends BaseAddon {
86328
86328
  const ids = [...this._permanentRestoreFailures.keys()].join(", ");
86329
86329
  return `${this._permanentRestoreFailures.size} device(s) permanently failed restore (deviceIds: ${ids}) — restart the ${this.providerName} provider to retry`;
86330
86330
  }
86331
+ /**
86332
+ * A top-level persisted row with NO configuration is a leftover, not a
86333
+ * device — quarantine it instead of dialling it.
86334
+ *
86335
+ * Device 614 was deleted, resurrected as a config-less shell by a write
86336
+ * already in flight (D376), and then dialled at every single boot: eight
86337
+ * `Failed to restore device — bounded retry scheduled` lines in one day,
86338
+ * each one the same Zod refusal on `host` and `password`. The bound was
86339
+ * real, but it is a bound PER PROCESS, and the runner restarts — so nothing
86340
+ * about the row ever stopped costing attempts and log lines.
86341
+ *
86342
+ * No retry can add a configuration that is not there. The row is reported
86343
+ * once, with its `deviceId`, and set aside.
86344
+ *
86345
+ * Top-level only: an accessory child legitimately carries an empty blob (it
86346
+ * lives off its parent), and a hub-adopted child with an emptied blob is
86347
+ * repaired by `healSavedConfig` from its parent instead. Providers that
86348
+ * genuinely create configuration-free top-level devices turn this off.
86349
+ */
86350
+ quarantineConfiglessTopLevelRestores = true;
86351
+ isUnrestorableShell(saved) {
86352
+ if (!this.quarantineConfiglessTopLevelRestores) return false;
86353
+ if (saved.parentDeviceId !== null) return false;
86354
+ const config = saved.config;
86355
+ if (config === void 0) return false;
86356
+ return Object.keys(config).length === 0;
86357
+ }
86358
+ quarantineShell(saved) {
86359
+ this._permanentRestoreFailures.set(saved.id, {
86360
+ deviceId: saved.id,
86361
+ stableId: saved.stableId,
86362
+ type: saved.type,
86363
+ attempts: 0,
86364
+ lastError: "persisted row has no configuration",
86365
+ failedAt: Date.now()
86366
+ });
86367
+ this.ctx.logger.error("Persisted device row has NO configuration — quarantined: not restored, not retried. Remove it (deviceManager.removeDevice) or re-add the device.", {
86368
+ tags: {
86369
+ deviceId: saved.id,
86370
+ stableId: saved.stableId
86371
+ },
86372
+ meta: {
86373
+ type: saved.type,
86374
+ provider: this.providerName
86375
+ }
86376
+ });
86377
+ }
86331
86378
  cancelRestoreRetries() {
86332
86379
  this._restoreRetryScheduler?.cancel();
86333
86380
  this._restoreRetryScheduler = null;
@@ -86512,6 +86559,10 @@ var BaseDeviceProvider = class extends BaseAddon {
86512
86559
  });
86513
86560
  return;
86514
86561
  }
86562
+ if (this.isUnrestorableShell(saved)) {
86563
+ this.quarantineShell(saved);
86564
+ return;
86565
+ }
86515
86566
  try {
86516
86567
  await attemptRestore(saved);
86517
86568
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-dreame",
3
- "version": "0.2.73",
3
+ "version": "0.2.75",
4
4
  "description": "Dreame robot-vacuum / lawn-mower device-provider addon for CamStack — wraps the @apocaliss92/nodedreame Dreamehome cloud client",
5
5
  "keywords": [
6
6
  "camstack",