-
-
Notifications
You must be signed in to change notification settings - Fork 403
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 more placeholders to rate-limit messages, move template interpolation from Rule
to Sopel
#2434
Add more placeholders to rate-limit messages, move template interpolation from Rule
to Sopel
#2434
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since I wanted to respond to the thread about public API concerns, thought I'd give the rest a quick skim too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been thinking a lot about rate limiting (yes, since yesterday evening when I said I went to bed, apparently that kept me awake for an hour or so...). I understand why you want to change the existing methods, yet I want to go another way: add more methods!
For instance, most of the logic is in the RuleMetrics
class: once you have it, you can ask if it is limited, and it contains most of the required information to format the rule's template for rate limiting.
Consider this:
@property
def user_rate_limit(self) -> datetime.timedelta:
return datetime.timedelta(seconds=self._*_rate_limit)
@property
def user_rate_template(self) -> Optional[str]:
return self._user_rate_message or self._default_rate_message
def get_user_metrics(self, nick: Identifier) -> RuleMetrics:
return self._metrics_nick.setdefault(nick, RuleMetrics())
Then you can have something like that:
triggered_at = datetime.datetime.utcnow()
user_rate_limit = rule.user_rate_limit
channel_rate_limit = rule.channel_rate_limit
global_rate_limit = rule.global_rate_limit
user_metrics = rule.get_user_metrics(trigger.nick)
channel_metrics = rule.get_channel_metrics(trigger.sender)
global_metrics = rule.global_metrics
metrics, template = None, None
if user_metrics.is_limited(triggered_at - user_rate_limit):
template = rule.user_rate_template
metrics = user_metrics
elif channel_metrics.is_limited(triggered_at - user_rate_limit):
template = rule.channel_rate_template
metrics = channel_metrics
elif global_metrics.is_limited(triggered_at - global_rate_limit):
template = rule.global_rate_template
metrics = global_metrics
message = None
if metrics and template:
message = template.format(...)
return RateLimitCheckInfo(limited=metrics is not None, metrics, triggered_at, message)
In the end, you still get an object that can tell you if 1. it was rate limited, 2. the data and metrics for that, and 3. the message to send if any! With some magic @property
you can even prevent yourself from having to pass the limited
, as it can be derived from the existence of a metrics
object.
73dbc70
to
d1b5c58
Compare
This PR is functionally complete now, but still needs a pass for testing and general quality (docstrings etc.) Edit: I figured out the cause of the following failures, read my later reply for more info Additionally, using
Looks like I suspect this is caused by some implicit dependence of the tests on the passage of time between the construction of a |
Haven't poked at all of the failing-with-
The Same happens for the second trigger in More tests than are throwing errors are failing with |
It turns out that these failures were caused by re-use of the triggers in these tests, failing to trigger the rate-limiting behavior because too much time had elapsed since the first event. Re-creating the triggers associated with the event resolves the failures. |
Rule
to Sopel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks better already!
A lot of nitpicking and formatting. In theory, the code works as expected, so it's not that important. The review is more about added quality than anything else.
The idea of adding a fixture to create a match for a rule and a trigger is nice. I'm not sure I would have made it that way, since I prefer when things don't have that many hard-coded text, otherwise it's cool to see the reduction in code repetition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the amount of commits you have, good luck with the squash that will inevitably be a nightmare. 😁
Remember that we use modules: short message
format for commits, not just for PR.
73bc5ff
to
dff0646
Compare
dff0646
to
ef3ffd2
Compare
Squashed this down as best as I could, but if it needs to be squashed any further, I think I might just discard all of the working history and re-arrange from scratch. Let me know if that needs done. |
CI failure is unrelated to the contents of this PR, seems to be an issue where CI has a more recent
This issue is being tracked upstream but probably we want to add a pin for (oops, I fat-fingered while typing this comment and accidentally closed this PR…) |
ef3ffd2
to
93c5e3c
Compare
Can I get a yes/no on the current squash of this PR? 12 commits still feels like a lot, but squashing to a single commit also feels excessive. |
LGTM. Reading the list of commits, each has a purpose that is clear and separate from other commits. Sure, we can see the progress "add this one, then this one, also fix that, change this, add another one", etc. and personally, I don't mind / I like it this way. Note that I don't mind either if you prefer to squash down to 2 or 3 commits (one for code, one for doc), I think both version of the history are acceptable. Maybe dgw has a stronger opinion, but from my perspective, LGTM! |
I don't mind the current history either, really. I tend to commit related code, docs, & tests all at once if I'm building an ideal history as I go, but doing that in a rebase can be error-prone so it's fine if you'd rather not go there. 😸 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc nitpicks, what would my self-identity be without them?
…rties Co-authored-by: dgw <dgw@technobabbl.es> Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com>
Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com> Co-authored-by: dgw <dgw@technobabbl.es>
Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com>
Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com>
Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com>
Co-authored-by: Florian Strzelecki <florian.strzelecki@gmail.com>
d44e3bb
to
9873465
Compare
Description
Fix #2325.
This changeset includes:
Sopel
andRule
Checklist
make qa
(runsmake quality
andmake test
)