Skip to content

Commit

Permalink
- Improved logging for rate limiters
Browse files Browse the repository at this point in the history
- Removed exception rising for unhandled event
  • Loading branch information
Alberto Geniola committed Oct 27, 2020
1 parent 5a4e832 commit 8216494
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0.6
0.4.0.7
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Due to the popularity of the library, I've decided to list it publicly on the Pi
So, the installation is as simple as typing the following command:

```bash
pip install meross_iot==0.4.0.6
pip install meross_iot==0.4.0.7
```

## Usage & Full Documentation
Expand Down Expand Up @@ -175,12 +175,14 @@ Anyways, feel free to contribute via donations!
</p>

## Changelog
#### 0.4.0.6
- Added device internal id parameter to async event handlers
#### 0.4.0.7
- Improved logging for API rate limiters

<details>
<summary>Older</summary>


#### 0.4.0.6
- Added device internal id parameter to async event handlers
#### 0.4.0.5
- Implemented MQTT rate-limiter
- Updated documentation
Expand Down
5 changes: 2 additions & 3 deletions meross_iot/controller/subdevice.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
from collections import deque
from datetime import datetime
from typing import Optional, Iterable

Expand Down Expand Up @@ -68,8 +67,8 @@ async def async_handle_push_notification(self, namespace: Namespace, data: dict)
_LOGGER.debug("Skipping temperature update as synched time is None or old compared to the latest data")
locally_handled = True
elif namespace == Namespace.HUB_SENSOR_ALERT:
raise NotImplementedError("TODO")
locally_handled = True
locally_handled = False
# TODO: not yet implemented

# Always call the parent handler when done with local specific logic. This gives the opportunity to all
# ancestors to catch all events.
Expand Down
19 changes: 17 additions & 2 deletions meross_iot/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ def _add_tokens(self):
def over_limit_percentace(self):
return (self._limit_hits_in_window / self._max_burst) * 100

@property
def current_stats(self) -> str:
perc = self._limit_hits_in_window / self._tokens_per_interval
return f"Limiter window: {self._window_interval_seconds} seconds, " \
f"HitRate: {self._limit_hits_in_window} ({perc}%)"

def check_limit_reached(self) -> bool:
# Add tokens if needed
self._add_tokens()
Expand Down Expand Up @@ -194,6 +200,15 @@ def __init__(self,
global_tokens_per_interval=requests_per_second_limit,
device_tokens_per_interval=requests_per_second_limit
)
_LOGGER.info("Applying rate-limit checker config: \n "
"- Global Max Burst Rate: %d"
"- Per-Device Max Burst Rate: %d"
"- Global Burst Rate: %d"
"- Per-Device Burst Rate: %d",
burst_requests_per_second_limit,
burst_requests_per_second_limit,
requests_per_second_limit,
requests_per_second_limit)

def register_push_notification_handler_coroutine(self, coro: Callable[
[GenericPushNotification, List[BaseDevice]], Awaitable]) -> None:
Expand Down Expand Up @@ -638,7 +653,7 @@ async def async_execute_cmd(self,

# In case the limit is hit but the the overlimit is sustainable, do not raise an exception, just
# buy some time
_LOGGER.debug(f"Rate limit reached: api call will be delayed by {self._over_limit_delay} seconds")
_LOGGER.warning(f"Rate limit reached: api call will be delayed by {self._over_limit_delay} seconds")
await asyncio.sleep(delay=self._over_limit_delay, loop=self._loop)
return await self.async_execute_cmd(destination_device_uuid=destination_device_uuid,
method=method, namespace=namespace, payload=payload,
Expand All @@ -663,7 +678,7 @@ async def _async_send_and_wait_ack(self, future: Future, target_device_uuid: str
return await asyncio.wait_for(future, timeout, loop=self._loop)
except TimeoutError as e:
_LOGGER.error(f"Timeout occurred while waiting a response for message {message} sent to device uuid "
f"{target_device_uuid}. Timeout was: {timeout} seconds")
f"{target_device_uuid}. Timeout was: {timeout} seconds.")
raise CommandTimeoutError()

async def _notify_connection_drop(self):
Expand Down

0 comments on commit 8216494

Please sign in to comment.