Queued offline updates#1430
Conversation
…e devices. When a firmware job completes successfully for a device that is currently offline, we set a new `queued_update` flag on the device. This indicates that the compiled firmware is ready and waiting to be flashed via OTA the next time the device checks in via mDNS.
…7/esphome-device-builder into queued-offline-updates
for more information, see https://pre-commit.ci
|
Will submit frontend to show queued status and option to cancel. Feedback appreciated. |
Core gap: |
|
|
esphbot
left a comment
There was a problem hiding this comment.
Blocking issues found — see the review comment above.
for more information, see https://pre-commit.ci
…7/esphome-device-builder into queued-offline-updates
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1430 +/- ##
=======================================
Coverage 99.54% 99.54%
=======================================
Files 224 224
Lines 17553 17614 +61
=======================================
+ Hits 17473 17534 +61
Misses 80 80
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
|
|
esphbot
left a comment
There was a problem hiding this comment.
Blocking issues found — see the review comment above.
|
This is dependent on this ESPHome PR - esphome/esphome#16358 |
Noted — feature can't function until esphome/esphome#16358 lands. Mark this PR draft until then. Two blockers independent of that dependency: |
|
|
esphbot
left a comment
There was a problem hiding this comment.
Blocking issues found — see the review comment above.
…gate offline update queuing logic, ensuring that devices are only queued once per offline state. This prevents redundant compile-only jobs for devices that are already marked as having a queued update, while still allowing new offline devices to be queued appropriately. Additionally, the test suite is updated to reflect the new flag and its behavior in the offline queue processing.
for more information, see https://pre-commit.ci
…7/esphome-device-builder into queued-offline-updates
for more information, see https://pre-commit.ci
|
|
esphbot
left a comment
There was a problem hiding this comment.
Blocking issues found — see the review comment above.
|
@codspeedbot fix this regression |
Likely cause: new |
PR Review — Queued offline updatesSolid scaffolding for queued offline OTA, but the wake→flash chain has a race that drops the install in its most common case, plus a hot-path perf regression and over-defensive reflective wiring. What's done well:
What needs attention:
🟡 Important1. Deferred install is silently dropped if the device wakes during compile (`esphome_device_builder/controllers/firmware/controller.py`, L444-453)The arming step in if is_comp and is_done and is_deferred:
device = self._device_for_configuration(job.configuration)
if device and device.state == DeviceState.OFFLINE and self._db.devices:
self._db.devices.set_queued_update(device.name, is_queued=True)If the device comes online during the compile (the common case — the user kicked off the install precisely because the device was about to wake, and a compile takes tens of seconds), the This is the exact moment the feature should fire (device available + binary ready), and it's the window the code doesn't cover. Consider: if the deferred compile finished and the device is currently ONLINE, fire the OTA upload directly instead of only arming-for-later; arm the flag only when still OFFLINE. 2. Flag cleared optimistically before the OTA upload runs — a failed flash loses the queued state (`esphome_device_builder/controllers/firmware/controller.py`, L99-110)
self._db.devices.set_queued_update(device.name, is_queued=False)
create_eager_task(self.upload(configuration=config, port="OTA"))If the OTA fails (device flaps back offline mid-flash, OTA auth/handshake failure, transient network), the flag is already gone, so the next wake won't retry. The user is left with an un-flashed device and a cleared queued state — the deferred install is lost on the first failed attempt, exactly the unreliable-network scenario the feature targets. Prefer clearing the flag only after a confirmed successful upload (e.g. on the upload job's 3. Per-event O(n) device scan on the DEVICE_STATE_CHANGED hot path (likely the CodSpeed regression) (`esphome_device_builder/controllers/firmware/controller.py`, L84-97)The new listener fires on every state change for every device, and return next((d for d in self._db.devices.get_devices()
if getattr(d, "configuration", None) == configuration), None)For a fleet, the mDNS/ping sweep flips many devices online/offline continuously, so this is O(devices) per O(events) — quadratic-ish churn on a hot path that previously did nothing. This is the most likely source of the CodSpeed regression flagged in the PR comment. The scanner already maintains indexed lookups ( 🟢 Suggestions1. Deferred install returns a COMPILE job with no dependent UPLOAD — diverges from the documented install contract (`esphome_device_builder/controllers/firmware/controller.py`, L258-270)Normal Combined with the unfilled Checklist
To rebase specific severity levels, mention me: Automated review by Kōan (Claude) |
esphbot
left a comment
There was a problem hiding this comment.
Blocking issues found — see the review comment above.
What does this implement/fix?
Add detection when device is offline to local build and add a queue flag that triggers an OTA when the device wakes.
Related issue or feature (if applicable):
Types of changes
bugfixnew-featureenhancementbreaking-changerefactordocsmaintenancecidependenciesFrontend coordination
Checklist
ruff,codespell, yaml/json/python checks).tests/where applicable.components.index.json/definitions/components/*.jsonhave not been hand-edited (regenerate viascript/sync_components.pyif a sync is needed).docs/ARCHITECTURE.mdand/ordocs/API.md.