-
Notifications
You must be signed in to change notification settings - Fork 117
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
remove refresh throttle #809
Conversation
Are you positive this is the root cause? The Throttle decorator will see the The reason this was added was because some instances in home-assistant would call refresh with |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## dev #809 +/- ##
==========================================
- Coverage 99.86% 99.86% -0.01%
==========================================
Files 8 8
Lines 1454 1453 -1
==========================================
- Hits 1452 1451 -1
Misses 2 2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Well... the decorator is removing the force=true which is preventing the updates at service calls in HA (with force=true). From updating. I suppose we could refresh in the API (if you can help me figure out how to do it in the camera.py module) or remove the decorator so that HA can do it... |
The issue is the Throttle decorator is throttling refresh to 2s. If removing that is fixing the problem, then the HA integration is calling refresh much too frequently and will almost certainly in accounts getting banned on Blink servers. As long as we have some sort of mechanism to ensure the integration can't spam refresh, that's fine. But I believe getting rid of the Throttle decorator removes that mechanism. So your alternative solution of removing it here and putting the burden on HA to solve it makes sense to me. Philosophically, we probably shouldn't be solving HA problems in this library anyways. Only reason I added that here originally was because...well...you see how long it takes to get PRs merged sometimes 😄 |
I'm not partial to this solution. It just took me a bit to figure out what the heck happened... Lines 133 to 135 in daea3cf
So maybe we should add local refresh for these calls that are not limited? What I believe is happening (based on some tracing)- we call an arm/disarm, then immediately try to refresh and it's throttled. When force = true, the throttle decorator POPs force (which I added awhile back because every function except refresh do not except force in the args) and then refresh doesn't see force. The solution we had for ARM/DISARM could be added to each of these calls too, and then leave the decorator. We probably only need to call a subset of Line 218 in daea3cf
Besides, maybe I'm reading this wrong, but refresh already has a limit built in doesn't it? Line 90 in daea3cf
check_if_ok_to_update - unless forced... Does it really need a throttle too?
I am not nearly as close to these functions and how the operate as your are. |
So all of this comes down to some historical context. This library was built for home-assistant, but not exclusively used by home-assistant. There's a decent amount of people that use it just as a python library and have their own scripts for arming/taking pics/etc. From the perspective of home-assistant: yes, we could just add throttles around API calls and be fine but this got annoying from a scripting perspective where you're maybe making a bunch of API calls all at once, but you only do it once (rather than HA which is constantly trying to refresh info). So I opted for a belt-and-suspenders approach of having a constant refresh time, but the ability to force to give flexibility. This is perfect for command line and then was also very useful for home-assistant users who would just spam Ultimately, though, I think you're right that adding throttles to the individual API calls vs the refresh makes the most sense. We would just have to make sure we add them in the right places and do a comparison between the logs to make sure all the logs are appropriately caught (probably a test for this would be best- write it with the existing lib and then make the modifications and make sure nothing breaks) |
Thanks for the context. As I am discovering even with HA, there are many various configurations that I had not tested. Lines 133 to 135 in daea3cf
Lines 150 to 153 in daea3cf
Lines 179 to 183 in daea3cf
etc... Line 90 in daea3cf
On the good side, the fellow over on the HA thread removed the throttle ONLY and it solved his arm system delay issue. I think it's safe to remove Throttle from this function only essentially leaving the API's throttled on one value, and the refresh function throttled on it's own value, assuming I understood what you've said above :) |
Yeah I know it will fix it but what I'm worried about are events where API calls are triggered too quickly via automations, etc which that testing wouldn't catch. It's more me worrying that I didn't implement throttling on all the correct API calls that So what I need to do (just haven't had time) is go through the refresh call and trace every API call that could be made and make sure throttling is on all the right ones. Right now my placement of that throttle decorator is a bit haphazard so I'm not totally convinced I have it all covered (hence me just throwing it around refresh and calling it a day). Re: built in throttle- the issue is when |
Oh believe me, I compare code to a "mold growth experiment" - put it in the dark and let it grow, see what happens :) On that note, I worked on moving to a switch platform for the motion detection function on the HA side, and this change also addressed the update problem in that as well. I'm hoping we have a solution in place for the 2023.12 release, but understand time is precious. |
I started going through the code and there are a ton of API calls not throttled that were covered by the refresh catch-all. If we add I think we need to remove the refresh pop from @Throttle(seconds=MIN_THROTTLE_TIME)
async def request_motion_detection_enable(blink, network, camera_id, **kwargs): While going back to this original implementation: 416b275 |
We can't really remove the pop: if you try to call any of the throttled functions they are not expecting a force argument and fail (all of the throttled components will fail the tests confirming force works). We could call refresh with force in the args twice - maybe that will do it? |
Yeah my suggestion is to add |
Given the history of Blink cutting off access prior to having the throttling in the library, I don't think this is a large enough sample size to confirm it's working reliably and think it's safer to retain the previous functionality |
Maybe something like this will work better now that we have asyncio?? |
Ooo that's interesting. I think that gives us the best of both worlds, right? Only question I'd have (related to asyncio) is what if I make like 1000 API calls within the throttle window? How does asyncio handle that? I have very little intuition for the library. (And I'm not saying that's a scenario we would want to plan for- I'd chalk that one up to user error. Just trying to understand where the limits are) |
Well, I was thinking this would holdup the "current" call until the throttle was finished then just make the call (which it does). This in theory would prevent a second call as it held up the flow of the application thread. If we call it concurrently, the second call is supposed to be delayed by now + 2*delta. I don't think this code achieves that. We may need it to do that too (I'm not sure). At this point, I think we're find removing the throttle decorator from refresh - maybe this is something in our back pocket if it breaks things for the general population... |
On second review, I think my proposed wrapper is broken - throttle_method needs to be awaited and it is not. |
Digging into the other PR #823, we do throttle the lower level |
Description:
After a bit of research into why HA wasn't updating the new switch platform (for camera motion detection), I found the throttle was poping force preventing the refresh from seeing "force". Since refresh already has a built in limiter, there is no need to put throttle in front.
We could just do this and it will solve the alarm control panel issue as well.
Related issue (if applicable): fixes #
Checklist:
tox
run successfully PR cannot be meged unless tests pass