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

Add group notification rate limits #36237

Closed
wants to merge 8 commits into from

Conversation

gjbadros
Copy link
Contributor

This enables per minute/hour/day rate limits for a notification group, and also makes it easy to enable/disable that notification group using an optional switch.

Breaking change

Proposed change

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example entry for configuration.yaml:

# Example configuration.yaml
notify:
  - name: greg_cameras
    platform: group
    services:
      - service: html5
    switch: switch.camera_notifs_enabled
    max_per_minute: 1
    max_per_hour: 12
    max_per_day: 50

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:
    Forthcoming after early feedback.

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

@probot-home-assistant
Copy link

Hey there @home-assistant/core, mind taking a look at this pull request as its been labeled with a integration (notify) you are listed as a codeowner for? Thanks!
(message by CodeOwnersMention)

@MartinHjelmare MartinHjelmare changed the title Added support for optional group notification rate limits and more Add group notification rate limits May 29, 2020

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_SERVICES): vol.All(
cv.ensure_list,
[{vol.Required(ATTR_SERVICE): cv.slug, vol.Optional(ATTR_DATA): dict}],
)
),
vol.Optional(CONF_SWITCH): cv.entity_id,
Copy link
Member

Choose a reason for hiding this comment

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

Remove this option. This can be handled via an automation or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the quick review & feedback, Martin!

The forums seem to have lots of suggestions about possibilities, but no one best way to do this. Moreover, I can't think of a way that adds the abstraction that I'm aiming for here, which is a notification channel that I can turn on and off independently. The alternatives I'm aware of are modifying every action to do this conditionally, and that's a very global change for such a simple intent.

What's the downside of the switch? It's a clean abstraction that meshes with rate limiting (it's a temporary rate limiting to 0; one could imagine programmable/dynamicall-changeable rate limits, but that seemed like overkill compared to a simple switch). And it's literally 4 lines of code with virtually zero runtime cost.

I hope you'll reconsider?

Copy link
Member

Choose a reason for hiding this comment

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

Why should we have a switch for this condition? The condition could be anything that has a binary state. I don't think this is the correct abstraction level.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed the config setting to 'enable_entity_id' to make clear that this works with any entity_id that supports is_on() (which just happens to be declared in switch.py). Is that what you were looking for?

And please let me know if there's a more refined vol check to statically enforce the guarantee that is_on() will work.. I think all entities support that since the check is just whether the state is STATE_ON.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should add this option at all here. I think we should think more about what the best way is to accomplish the use case of this PR.

Maybe we should create some kind of general throttled action with a target action and options for the rate limit of the throttle?

I suggest making an architecture issue.

self.calls_minute = deque()
self.calls_hour = deque()
self.calls_day = deque()
self.lock = threading.Lock()
Copy link
Member

Choose a reason for hiding this comment

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

We can't use a threading lock in async context. Only asyncio locks are allowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, good catch... will fix to use asyncio.lock. Thx!

Dev automation moved this from Needs review to Review in progress May 29, 2020
@gjbadros
Copy link
Contributor Author

gjbadros commented May 29, 2020 via email

@balloob
Copy link
Member

balloob commented May 29, 2020

We should not merge this PR.

Rate limiting and conditional calling things should be implemented as generic wrappers of any service. They should not be hacked into existing services because we would end up with having to add this to every service !

Conditional calling is already available by wrapping a service in a script with a condition. Rate calling should be implemented likewise.

@balloob balloob closed this May 29, 2020
Dev automation moved this from Review in progress to Cancelled May 29, 2020
@gjbadros
Copy link
Contributor Author

What's the right place to discuss this stuff in advance of submitting a PR?

Nobody seems to comment on most feature requests -- e.g., https://community.home-assistant.io/t/scripts-need-a-finally-sequence-block/183424 where I still have no guidance on whether a PR to implement that would be accepted.

I like your idea of doing this inside a script, and think that's reasonable too/instead. I do think that notifications are very explicitly something that people expect to have rate-limiting controls on.

N.B., that notify.group could've been implemented using a script to notify multiple notification channels, but it wasn't done like that because it's a nice abstraction, just like I think this was.

@balloob
Copy link
Member

balloob commented May 29, 2020

Best place to discuss this is in the architecture repository, as it requires a new addition to the script syntax. See also a similar discussion about extending synax

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

Successfully merging this pull request may close these issues.

None yet

4 participants