Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors and exceptions handling improvement #43

Merged
merged 10 commits into from
Apr 9, 2024

Conversation

MrXANA91
Copy link
Contributor

@MrXANA91 MrXANA91 commented Mar 22, 2024

This PR aims to fix #36 and to generally improve the exceptions potentially raised by the integration using the Home Assistant exception classes

If the Switchbot servers return a 500 status, the integration will send a warning to the Home Assistant logs.
It will wait 0.5s and will then try to resend the same command.
After 5 consecutive 500 status failures, it will (should ?) abort and raise an error to Home Assistant.

@MrXANA91
Copy link
Contributor Author

Currently testing this version on my HA instance.

I have tested by forcing a returned status to 500 at random, and it effectively resends the same request after 0.5s repeatedly, until the return status is 200. If the 5 tries all failed with 500, then it aborts and raise a SwitchbotInternal500Error exception to the Home Assistant core.

@MrXANA91
Copy link
Contributor Author

MrXANA91 commented Apr 5, 2024

And of course, since I started testing this fix, the 500 error status no longer appear for me ...

Making it ready for review anyway, still testing

@MrXANA91 MrXANA91 marked this pull request as ready for review April 5, 2024 19:32
Copy link
Owner

@KiraPC KiraPC left a comment

Choose a reason for hiding this comment

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

Just a little feedback. Other is ok


_LOGGER.debug(f"Call service {url} OK")
return response_in_json

def filtered_request(self, method: str, path: str, **kwargs) -> Any:
Copy link
Owner

Choose a reason for hiding this comment

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

@MrXANA91 I don't like to have unused code, what about the request api? Is it still used?

In case not, change request api instead of add a new one, and add a parameter for "retry" that could be MAX_TRRIES as default and with 0 you should have the same behavior of the old request implementation.

Copy link
Contributor Author

@MrXANA91 MrXANA91 Apr 5, 2024

Choose a reason for hiding this comment

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

If you check line 73, you can see a call to the request API. filtered_request just wraps the current request method to catch any 500 status that could potentially appear.

First request is sent (considered first try). If a 500 status is caught and MAX_TRIES is greater than 1, the request is resent after waiting 500ms (or the value of DELAY_BETWEEN_TRIES_MS). If every requests throw a 500 error code, a total number of MAX_TRIES (here is 5) requests will be sent before an error pops up in Home Assistant.

If you set the value of MAX_TRIES to 1, this code will behave exactly like it currently does in the release.

Copy link
Owner

Choose a reason for hiding this comment

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

mmmm ok, good point. Anyway, I don't like the name, why it is filtered?

Could you use for:else (https://www.w3schools.com/python/gloss_python_for_else.asp) returning the result instead of breaking the loop?

Copy link
Owner

Choose a reason for hiding this comment

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

Anyway, I prefer to make request "private" -> so you could name your method request and I would like to accept the retry as parameter that per default it is equals to MAX_RETRIES

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, I'll make the changes.

Do you want the delay value as a parameter as well?

Copy link
Owner

Choose a reason for hiding this comment

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

Yup, that's great.

Thanks a lot for your help and passion!

- setting original 'request' method as private
- renamed 'filtered_request' to 'request'
- maxNumberOfTrails defaults to MAX_TRIES
- delayMSBetweenTrials defaults to DELAY_BETWEEN_TRIES_MS
for tryNumber in range(maxNumberOfTrials):
try:
result = self.__request(method, path, **kwargs)
break
Copy link
Contributor Author

@MrXANA91 MrXANA91 Apr 5, 2024

Choose a reason for hiding this comment

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

@KiraPC
I have to keep the break statement at this location in order to get out of the loop if the request succeeds.
I added the else statement which is better than checking the tryNumber but I don't think that I can get rid of the break statement unless I completely rethink the way the trials are handled.

Copy link
Owner

Choose a reason for hiding this comment

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

@MrXANA91 As I suggested, you should use a return statement in case of success directly inside the try block, and the else statement is executed just when the loop end without result

@MrXANA91 MrXANA91 requested a review from KiraPC April 5, 2024 23:16
Copy link
Owner

@KiraPC KiraPC left a comment

Choose a reason for hiding this comment

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

Have you tested and everything works as expected?

@MrXANA91 MrXANA91 marked this pull request as draft April 6, 2024 14:46
@MrXANA91
Copy link
Contributor Author

MrXANA91 commented Apr 6, 2024

Going back to draft during testing

Not tested yet, I'll let you know

@MrXANA91
Copy link
Contributor Author

MrXANA91 commented Apr 8, 2024

A few minutes ago, when trying to send a turn_off command, i've noticed a unusual slightly longer delay between me pressing the button and the AC signaling a received command.
When checking the logs, here is what I've found :

1-Caught 500

...
2024-04-08 19:35:00.318 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.remote] Sending command turnOff
2024-04-08 19:35:00.318 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.remote] Command payload {'commandType': 'command', 'command': 'turnOff', 'parameter': 'default'}
2024-04-08 19:35:00.318 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.client] Calling service https://api.switch-bot.com/v1.1/devices/01-202404032246-40583347/commands
2024-04-08 19:35:00.662 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.client] Received http error 500 {"message": "Internal server error"}
2024-04-08 19:35:00.662 WARNING (SyncWorker_27) [custom_components.switchbotremote.client.client] Caught returned status 500 from SwitchBot API server
2024-04-08 19:35:00.662 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.client] tryNumber = 0, waiting 500 ms
2024-04-08 19:35:01.164 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.client] Calling service https://api.switch-bot.com/v1.1/devices/01-202404032246-40583347/commands
2024-04-08 19:35:01.694 DEBUG (SyncWorker_27) [custom_components.switchbotremote.client.client] Call service https://api.switch-bot.com/v1.1/devices/01-202404032246-40583347/commands OK
...

So the fix is actually working properly. Marking it as ready!

@MrXANA91 MrXANA91 marked this pull request as ready for review April 8, 2024 17:56
@KiraPC
Copy link
Owner

KiraPC commented Apr 9, 2024

Great, merging

@KiraPC KiraPC merged commit e0a531a into KiraPC:main Apr 9, 2024
2 checks passed
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.

Handling status 500 from SwitchBot servers
2 participants