Fix: timed-out support-code request silently treated as successful - #41
Open
githubhjs wants to merge 4 commits into
Open
Fix: timed-out support-code request silently treated as successful#41githubhjs wants to merge 4 commits into
githubhjs wants to merge 4 commits into
Conversation
publish()'s "support" closure called Event.wait(timeout) but discarded its return value, so a genuine timeout (no MQTT response ever arrives) was indistinguishable from a real response once _wrap_async unconditionally returned the thing_name identifier. This made refresh_status() take the wrong branch in its result-gathering loop — it saw the thing_name in support_results and assumed a response had arrived, then hit the "event occurred but wasn't accompanied with data" RuntimeError instead of the existing, correctly-worded "Timed out refreshing ... support code" path that already exists for this exact situation. Verified against a real account with two devices, one of which reproducibly times out waiting for its support-code response (3/3 attempts) while the other succeeds reliably (3/3 attempts). Before this fix, the failing device raised the misleading "wasn't accompanied with data" message; after, it correctly raises the existing timeout message. The working device is unaffected (3/3 successful logins after the change). See qqaatw#40 for the original report and full reproduction details. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
for more information, see https://pre-commit.ci
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #41 +/- ##
==========================================
- Coverage 92.63% 87.81% -4.82%
==========================================
Files 8 8
Lines 787 788 +1
==========================================
- Hits 729 692 -37
- Misses 58 96 +38 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Owner
|
Thanks. Wonder if we should handle the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the root cause behind #40 (and the same symptom in the older closed reports #38/#31/#40 on
JciHitachiHA).Root cause
In
JciHitachiAWSMqttConnection.publish(), the"support"branch's innerfn()called:...and discarded the return value.
threading.Event.wait(timeout)returnsFalseon a genuine timeout, but since_wrap_async()always returns thething_nameidentifier unconditionally (regardless of whatfn()internally observed),execute()'ssupport_resultsends up containing the thing name even when the device never responded at all.This violates
execute()'s own documented contract ("Each result is a list containing thing names if the execution was successful orBaseException(s) if an error occurred") and causesrefresh_status()to take the wrong branch when gathering results — it seesthing.thing_name in support_results, assumes a response arrived, and raises:...instead of correctly falling into the
elsebranch that already exists for this exact case, with a much more accurate and actionable message:So the fix is small: make the timeout actually raise inside
fn(), soasyncio.gather(..., return_exceptions=True)correctly captures it as an exception rather than a false-positive success.Fix
Testing
Verified against a real account with two devices — one that reproducibly fails this exact way (3/3 attempts, isolated via
device_names=) and one that reliably succeeds (3/3 attempts). Results:RuntimeError: ...wasn't accompanied with data...RuntimeError: Timed out refreshing... Please ensure the device is online...(correct, existing message)LOGIN OKLOGIN OK(unchanged)No behavior change for devices that respond normally — this only changes what happens when a device's support-code request never gets a response, replacing a misleading error with the message the code already intended to show in that case.
Scope note
The
"status"and"control"branches of the samepublish()method have the identical discard-the-wait-result pattern and likely have the same latent issue. I scoped this PR to just"support"since that's the specific reported/reproduced case — happy to open a follow-up for the other two if that's wanted, but didn't want to change more behavior than I could actually verify against a live reproduction.