Skip to content

Fetch each port once and drop the fixed 10 second refresh timeout - #151

Open
tkolsto wants to merge 1 commit into
dalinicus:mainfrom
tkolsto:fix/refresh-scaling
Open

Fetch each port once and drop the fixed 10 second refresh timeout#151
tkolsto wants to merge 1 commit into
dalinicus:mainfrom
tkolsto:fix/refresh-scaling

Conversation

@tkolsto

@tkolsto tkolsto commented Aug 18, 2026

Copy link
Copy Markdown

Problem

ACInfinityDataUpdateCoordinator._async_update_data wraps the entire refresh in a fixed async_timeout.timeout(10). But refresh() makes one sequential API call per controller plus per port — and it currently fetches every port twice, since port controls and port settings both come from the same getdevModeSettingList response.

Refresh duration therefore grows linearly with account size. Measured against a real account with 13 controllers / 68 ports: 150 sequential calls at ~288 ms/call with connection reuse ≈ 43 seconds — against a 10 second ceiling. Once an account grows past roughly 3 controllers' worth of ports, no refresh can ever complete: every poll times out, UpdateFailed is raised, and every entity of every controller is permanently unavailable. Removing and re-adding the integration doesn't help, because the first refresh fails the same way.

The user-visible symptom is "the integration just stopped getting data one day" — the day the account crossed the size threshold. Field-confirmed: a user with exactly this symptom (all devices visible, every value blank, reinstall didn't help) had data restored immediately by this change.

This may also explain the anomalous ~1m49s polling gap in the debug log attached to #146.

Changes

  1. Fetch each port once. Store both port controls and port settings from a single getdevModeSettingList response instead of requesting it twice. Halves the number of calls per refresh.
  2. Remove the overall 10 second refresh timeout. Every request already has its own 10 second timeout inside the client, and the retry logic bounds failures, so total refresh duration is already bounded — the blanket wrapper adds nothing except a hard ceiling on account size.

For users with larger accounts it's still worth raising the polling interval in the integration options, since a refresh that takes ~20 s shouldn't be scheduled every 10 s — but with this change a large account degrades to "slow" instead of "permanently unavailable". (Parallelizing the per-port fetches would speed this up further, but given the API's sensitivity to request bursts (#39) I kept this PR to the conservative fixes.)

Testing

  • Full suite passes: 1764 (1763 baseline + 1 new regression test asserting exactly one settings fetch per port, with controls and settings both populated from it). pyright clean.
  • Field-verified on a 13-controller account that was fully dead on 2.2.0: data returned immediately after installing a build with this change.

Independent of #149 and #150; merges cleanly with both.

Refresh made two identical getdevModeSettingList calls per port (controls
and settings both come from the same response), and the data update
coordinator wrapped the whole refresh in a fixed 10 second timeout even
though every request already has its own 10 second timeout in the client.

Refresh duration grows with account size: one call per controller plus
one per port, all sequential. Measured against a real 13 controller / 68
port account this is ~43 seconds with connection reuse, so the refresh
can never complete inside the 10 second window. Every update then fails
with a timeout and every entity of every controller is permanently
unavailable, which users experience as the integration silently showing
no data even after re-adding it.

- Store port controls and port settings from a single fetch per port
- Remove the overall refresh timeout; per-request timeouts and the
  bounded call count already limit the total duration
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant