Skip to content

fix(go-sdk): preserve matched device when BLE scan completes - #13057

Open
bobbyhuang-dev wants to merge 3 commits into
BasedHardware:mainfrom
bobbyhuang-dev:fix/go-ble-scan-completion
Open

bobbyhuang-dev wants to merge 3 commits into
BasedHardware:mainfrom
bobbyhuang-dev:fix/go-ble-scan-completion

Conversation

@bobbyhuang-dev

@bobbyhuang-dev bobbyhuang-dev commented Sep 8, 2026

Copy link
Copy Markdown

What changed and why

Fixes #13056. A successful Go BLE scan can make both the matching-address channel and scan-completion channel ready; receiving completion first incorrectly returned “device not found.” Preserve the queued match before treating a completed scan as empty.

The unexported adapter interface lets regression tests exercise the real connection function without Bluetooth hardware. Both Go SDK suites are registered in the shared preflight manifest, with Go setup scoped to SDK/check-configuration changes in the existing Hygiene job.

Product invariants affected

none

How it was verified

  • macOS arm64, Go 1.27.1, upstream b7fc348e5170e02c44c5070c479c1438daac03af.
  • Before the fix, the real connection function with an injected fake adapter failed on matching scan 98 with device ... not found.
  • After the fix, all 1,000 matching scans pass; empty scans still return not found, and scan errors retain their original cause.
  • go test ./...: pass.
  • go test -tags ble ./...: pass.
  • go test -race -tags ble ./...: pass.
  • git diff --check: pass.
  • OMI_PR_BODY_FILE=... make preflight: pass (21 selected checks). The failure-class history ratchet explicitly skipped its 90-day analysis because this is a shallow clone; CI must enforce that check with full history.

The two backend workflow test files selected by the push hook also pass through BACKEND_UNIT_TEST_FILE_LIST=... bash backend/test.sh. The hook’s full-backend prerequisite check cannot run in this SDK-focused environment, so the push uses its documented PRE_PUSH_SKIP_BACKEND_UNIT_TESTS=1 option after that focused run. No full backend-suite result is claimed.

The test exercises production connection selection against a fake adapter. Physical-device behavior and the Linux CI run have not been verified locally.

Tests

sdks/device/go/omidevice/ble_tinygo_test.go covers the successful-scan race, empty scans, and scan errors. Tests make no adapter connections or network requests and use no sleeps.

Failure class (fixes)

Failure-Class: none

New guards

The manifest checks cover the reproduced connection failure in #13056. They execute the SDK's existing shared connection primitive through an injected adapter; a separate production wrapper would not verify the channel-ordering contract.

Contribution note

The proposed US$25 PayPal bounty in #13056 is pending maintainer confirmation; no award or payment is assumed.

Failure-Class: none

Reproduced device-not-found on successful scan before the fix. Default Go tests, BLE tests with race detector, and make preflight (21 selected checks) pass. Physical Bluetooth hardware was not tested. Shallow-history ratchet deferred to CI.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/repo-checks.yml Outdated
Failure-Class: none

Align setup path selection with the Go manifest triggers. Verified make preflight: 21 checks pass; existing shallow-history limitation remains documented.
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Verified end to end against 0629e00 - this is a well-scoped fix for a real race, with the kind of issue writeup and hardware-free regression coverage that makes it easy to review. Credit for that.

Per-file notes:

  • sdks/device/go/omidevice/ble_tinygo.go - the non-blocking select { case addr = <-found: default: ... } added to the scan-completion branch is the correct minimal fix: the callback queues found before StopScan(), so when Scan returns before the outer select runs, both channels are ready and the old code discarded a queued match. I rebuilt the pre-fix completion branch on top of the new connectionAdapter parameterization and the regression test fails within a few runs on multi-core Linux (while passing 1000 iterations single-threaded - the window is scheduler-dependent, consistent with the macOS reproduction in Go device SDK can report device not found after a successful scan #13056); the head passes -race -tags ble under the same stress. The interface mirrors exactly the three *bluetooth.Adapter methods connect uses, and the production call sites still pass bluetooth.DefaultAdapter.
  • sdks/device/go/omidevice/ble_tinygo_test.go - covers all three completion paths: match preserved across scan completion, empty scan returns 'not found', and scan errors keep their cause (errors.Is passes through the %w wrap). matchingAdapter.Scan invoking the callback synchronously then returning nil is a faithful model of the winning-completion race, and the connected flag asserts no connect happens on the empty/error paths.
  • .github/checks-manifest.yaml - both new entries run exactly the commands verified above; lanes: [local, ci] satisfies the manifest validator's both-lanes requirement, and the Go device SDK can report device not found after a successful scan #13056 reasons are accurate.
  • .github/workflows/repo-checks.yml - gating setup-go on sdks/device/go/ changes resolves the earlier review thread here. One residual edge, non-blocking: a future manifest-only edit to these two entries will still select the Go checks (via the manifest-changed path) without triggering the setup step, leaning on the runner's ambient Go or toolchain auto-download. If that ever produces a confusing failure, widening the grep is a one-liner.
  • sdks/device/go/README.md - accurate: both suites are registered for local and ci lanes, and 'Go 1.23.8 or later' matches the go.mod floor (CI pinning 1.26.7 is fine).

For the maintainer record, two non-blocking notes: all nine check suites on this head are action_required (first-PR workflow approval), so nothing has actually run in CI - the verification above was done in an isolated container instead; and the workflow/manifest wiring deserves a quick look when approving the runs so the new Go checks can validate the fix in CI.

Leaving for human maintainer review: CI-workflow additions from a first-time contribution need maintainer sign-off before the checks can run.

Automated maintainer feedback, generated with AI assistance on the maintainers' behalf.


by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.

@Git-on-my-level Git-on-my-level added positive-signal Automation verified a genuine fix/quality contribution workflow-review Needs maintainer review for workflow, automation, hooks, or CI behavior labels Sep 8, 2026
Resolve .github/checks-manifest.yaml by preserving main's race-enabled
Go SDK check and the PR's separate race-enabled BLE regression suite.
Keep main's platform selection and Parakeet handshake rationale.

Validation on macOS arm64 with Go 1.27.1:
- go test -race ./...: passed.
- go test -race -tags ble ./...: passed.
- python3 .github/scripts/test_run_checks.py: 52 tests passed.
- git diff --cached origin/main --check: passed.
- Independent review: approved; final PR diff remains five files.
- OMI_PR_BODY_FILE=... make preflight: 21 selected checks passed.
  The 90-day failure-class history ratchet skips on this shallow clone;
  CI remains responsible for enforcing it with full history.
- Pinned actionlint v1.7.12 on repo-checks.yml: passed.
- PYTHONPATH=backend backend/.venv/bin/python -m pytest --noconftest -q
  backend/tests/unit/test_changed_files_script.py
  backend/tests/unit/test_workflow_contracts.py: 28 passed.
  These focused script tests need no backend-wide conftest fixtures.

This merge imports existing main changes. The pre-commit autoformatter
is omitted to avoid rewriting inherited source files; the resolved
manifest, author identity, and final PR diff are validated directly.
Full backend dependency setup is outside this Go SDK conflict resolution.
The push uses PRE_PUSH_SKIP_BACKEND_UNIT_TESTS=1 after the focused tests
above; no full-backend test-suite result is claimed.

Failure-Class: none
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Reviewed the merge head f7e216f (merge of main into fix/go-ble-scan-completion). The PR-owned files (sdks/device/go/omidevice/ble_tinygo.go, ble_tinygo_test.go, README section) are unchanged from 0629e00, which was already verified end to end; the new risk in this head is the .github/checks-manifest.yaml conflict resolution, and it is correct: main's race-enabled go-device-sdk-tests (from the Parakeet readiness work) is preserved alongside this PR's go-device-sdk-ble-tests, with main's platform selection and rationale kept. The repo-checks.yml Go setup stays gated on sdks/device/go/ changes per the earlier review note about trigger overlap.

I re-ran the suites on this head in a clean Linux container: go test ./..., go test -race -tags ble ./..., and repeated -race runs of the three connect tests all pass; the matchingAdapter fake exercises the winning-completion ordering without Bluetooth hardware.

Note there were no CI check runs on this head at review time, so the merged manifest selection still needs a green preflight run. The workflow/manifest additions remain under workflow-review for maintainer sign-off; the fix itself is in good shape.


by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.

@bobbyhuang-dev

Copy link
Copy Markdown
Author

Thanks for re-verifying the merge head and checking the manifest conflict resolution. I appreciate the independent reproduction and race-test coverage.

I’ll keep the current scope unchanged: main’s race-enabled Go SDK check and its platform selection are preserved alongside the BLE regression check, and Go setup remains gated on SDK changes as requested in the earlier review.

The current head still has no CI check runs. Could a maintainer review/sign off on the workflow and manifest changes and approve or trigger the applicable workflows so the merged manifest selection can get a green preflight run? I’ll address any failures that surface.

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

Labels

positive-signal Automation verified a genuine fix/quality contribution workflow-review Needs maintainer review for workflow, automation, hooks, or CI behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go device SDK can report device not found after a successful scan

2 participants