Skip to content

fix(wda): keep enough connections open for four requests at once - #181

Merged
omnarayan merged 1 commit into
devicelab-dev:mainfrom
vyrahealth:upstream-pr/wda-keep-idle-connections
Oct 1, 2026
Merged

omnarayan merged 1 commit into
devicelab-dev:mainfrom
vyrahealth:upstream-pr/wda-keep-idle-connections

Conversation

@bulatgaleev

@bulatgaleev bulatgaleev commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The WDA driver sends up to four requests at once: an element's name, rect, text and displayed are read in parallel, and a tap looks an element up four ways at once. Its HTTP client used Go's default transport, which keeps two idle connections per host, so every burst closed two connections and opened two new ones. On a physical iPhone reached through a forwarded port (SSH, then iproxy over USB), a new connection costs about 300 ms, and new connections opened together fail at once with EOF. The client now keeps up to eight idle connections per host.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional changes)

Changes Made

  • The WDA client's transport is a clone of http.DefaultTransport with MaxIdleConnsPerHost set to 8.
  • pkg/driver/wda/kept_connections_test.go: 50 bursts of four reads open 4 connections instead of 102, and through a server that drops every new connection past the first four, no read fails. The old client lost 23 reads there, after 196 dropped connections.
  • CHANGELOG.md entry.

Related Issues

No existing issue found.

Testing

  • go test ./pkg/driver/wda/
  • Added tests for new functionality
  • Running on a physical iPhone (iOS 27, WebDriverAgent reached through a forwarded port) in our nightly 46-flow suite, as part of our fork's build. Before the change, one 44-flow run on that phone had 297 of 996 bursts lose exactly two reads (the two new connections) and 2 lose one, while no read on a kept connection failed. WebDriverAgent does not close idle keep-alive connections, so a stale reuse was not the cause.
  • go vet ./... and make fmt-check pass (run on the top of the stack, fix(wda): checked selectors work on iOS #185, which contains all five changes)
  • make test as a whole: not run, because its device tests drive whatever device is attached to the machine
  • make lint: the Makefile has no lint target, and the linters make check runs (staticcheck, revive, errcheck, nilaway, gosec) are not installed here

Checklist

  • Code follows project style guidelines
  • Self-reviewed the code
  • Added/updated documentation as needed (no documentation change needed)
  • No breaking changes (or documented if breaking)
  • CHANGELOG.md updated (for notable changes)

Additional Notes

Stack 1 of 5: #181 → #182 → #183 → #184 → #185. Merge in that order. This is the base of the stack; its change is 17d9d27. All five sit on main at fe3dd53 (the 1.1.28 release).

@bulatgaleev

Copy link
Copy Markdown
Contributor Author

@omnarayan, when you have a moment, could you take a look at this stack? It is five small fixes, each bringing maestro-runner's behaviour in line with Maestro's, with tests and a CHANGELOG line:

They are stacked in that order so that merging one never conflicts with the next, and each description now follows the PR template. We run all five on a physical iPhone in our nightly suite. Happy to split, rebase or change anything that would make them easier to review.

The WDA driver reads an element's name, rect, text and displayed in
parallel, and a tap looks an element up four ways at once. The client used
Go's default transport, which keeps two idle connections per host, so every
such burst closed two connections and opened two new ones.

On a real iPhone reached through a forward (SSH, then iproxy over USB) a
new connection costs about 300 ms, and new ones opened together fail at
once with EOF. In one 44-flow run, 297 of 996 element bursts lost exactly
two reads (the two new connections), 2 lost one, and none lost a read on a
kept connection: 976 EOFs, each sent again by the dropped-connection
retry. WebDriverAgent does not close an idle keep-alive connection
(FBHTTPServer exempts them from its reaper), so a stale reuse was not the
cause.

The client now keeps up to eight idle connections per host. In the new
tests, 50 bursts of four reads open 4 connections instead of 102, and
through a server that drops every new connection past the first four, no
read fails (the old client lost 23 reads there, after 196 dropped
connections).
@bulatgaleev
bulatgaleev force-pushed the upstream-pr/wda-keep-idle-connections branch from 4abbe50 to 17d9d27 Compare September 30, 2026 14:49
@omnarayan

Copy link
Copy Markdown
Contributor

Thank you @bulatgaleev, and thanks for the measurements: 976 EOFs traced to the default transport's two idle connections is exactly the kind of detail that makes this easy to review.

The change is small and WDA-only, and it merges cleanly on today's main. We're merging this PR and the rest of your stack (#182–#185) into main now. They will ship in 1.1.29. 1.1.28 went out today, so they missed it.

@omnarayan
omnarayan merged commit 0cdc5ad into devicelab-dev:main Oct 1, 2026
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.

2 participants