Skip to content

perf(cli): Probe USB Homey candidates in parallel - #674

Open
RobinBol wants to merge 1 commit into
developfrom
fix/parallel-usb-probe
Open

RobinBol wants to merge 1 commit into
developfrom
fix/parallel-usb-probe

Conversation

@RobinBol

Copy link
Copy Markdown
Contributor

What

Local Homey discovery probes its candidate USB addresses concurrently, and only once per subnet.

Why

getHomeys() looks for a USB-connected Homey by pinging 10.x.y.1 for every network interface whose address starts with 10.. Those probes ran one after another with a one second timeout each, so every such interface that is not a Homey added a full second to any command that has to resolve a Homey first, including homey api ..., homey list and homey select.

Virtualization tools routinely add a couple of 10.x adapters to a machine, and none of them ever answer. Two interfaces in the same subnet made it worse: both map to the same candidate address, so that address was probed twice, each time for the full timeout.

How

Collect the unique candidate addresses first, then run the probes with Promise.all. The timeout, the request and the id matching are unchanged, so the cost is now bounded by the one second timeout instead of scaling with the number of interfaces.

Testing

Measured with os.networkInterfaces stubbed to report dead 10.x adapters and the rest of getHomeys stubbed out:

interfaces before after
4, two of them in one subnet 4006ms, 4 probes 1004ms, 3 probes
8 9012ms 1005ms

End to end on a machine with three such interfaces (two from a virtualization tool, one from a VPN tunnel), running homey api raw --path /api/manager/system/ against a real Homey over the cloud strategy: 3.05s, 3.12s, 3.14s before, 1.94s, 1.97s, 1.99s after.

  • tests/lib/athom-api.fetch.test.mjs gains a case that holds every probe open until all of them have started, so a sequential implementation cannot reach the second address. It fails on the previous implementation and needs no timers.
  • Full suite: 233 passing, with the same 6 pre-existing environment-dependent failures as on develop (Docker host address and completion fixtures).
  • eslint --max-warnings=0 and prettier --check are clean.

Local discovery probed one candidate address per network interface
sequentially, each with a one second timeout, so every 10.x interface that
is not a Homey added a full second to getHomeys. Virtualization adapters
commonly add several of those. Interfaces sharing a subnet also produced a
duplicate probe for the same address.

Collect the unique candidate addresses first, then probe them concurrently.
With four such interfaces, two of them in one subnet, this drops from
4006ms to 1004ms; with eight it drops from 9012ms to 1005ms. The total is
now bounded by the timeout instead of scaling with the interface count.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation is focused, preserves existing discovery behavior, and includes appropriate regression coverage.

Pull request overview

Parallelizes and deduplicates USB Homey discovery probes, reducing discovery latency.

Changes:

  • Collects unique candidate IPs before probing.
  • Probes candidates concurrently with unchanged timeout behavior.
  • Adds coverage for concurrency and subnet deduplication.
File summaries
File Description
lib/AthomApi.js Deduplicates and parallelizes USB discovery probes.
tests/lib/athom-api.fetch.test.mjs Verifies concurrent, unique probing.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants