Conversation
Looking at this now. |
Yes, I think so. I should be able to correct it by editing the commit when I rebase. (Learned something new - I didn't know that signing as |
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.
Nice, clear implementation. I was able to successfully exercise this using real API calls from the Swagger page and see both notifications being sent when they should.
I added a question and made some relatively small suggestions
- DJANGO_LOG_LEVEL=INFO | ||
- AWS_PROFILE=${AWS_PROFILE:-open-apparel-registry} | ||
- OAR_CLIENT_KEY= | ||
- NOTIFICATION_EMAIL_TO=notification@example.com |
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.
Noting for the PR history that this appears to be only content change in this file. The rest is whitespace cleanup.
src/django/api/limits.py
Outdated
).values('contributor').annotate(request_count=Count('id')) | ||
for c in contributor_logs: | ||
contributor = Contributor.objects.get(id=c.get('contributor')) | ||
with transaction.atomic(): |
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.
Consider moving the logic inside this for
loop into a helper function and decorating the helper function with @transaction.atomic
. For each loop iteration we want all of our reads and writes to the database to be consistent. Future editors of the logic will not have to worry about if they need introduce or move a with transaction block.
src/django/api/limits.py
Outdated
return (at_datetime.replace( | ||
day=1, hour=0, minute=0, second=0, microsecond=0) | ||
+ relativedelta(months=1) - relativedelta(seconds=1)) \ | ||
.replace(tzinfo=timezone.utc) |
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'm curious about this final updating of the tzinfo
. Does adding and removing relativedelta
s strip the timezone information resulting in our need to replace it?
src/django/api/limits.py
Outdated
until = get_end_of_month(at_datetime) | ||
with transaction.atomic(): | ||
ApiBlock.objects.create(contributor=contributor, | ||
until=until, active=False, |
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.
If we are creating a new ApiBlock
because the contributor has exceeded their limit, as I understand it that we should be setting active=True
since we want to block further request to the API until we reach the until
date.
@@ -0,0 +1 @@ | |||
Open Apparel Registry contributor API limit notice |
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.
Consider changing this admin-facing email title to include the contributor name so that mail clients don't "helpfully" stack up notifications for different contributors.
One possibility
OAR API limit exceeded - {{contributor_name}}
</p> | ||
{% if grace_limit %} | ||
<p> | ||
The grace limit previously set was {{ grace_limit }}. |
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.
While testing I realized that we are being more detailed about our limit calculations than we absolutely have to be.
Consider this simplified version that excludes the current count
{% if grace_limit %}
<p>
You're receiving this email because you have exceeded
your limit of {{ grace_limit }} OAR API requests for this month.
</p>
{% else %}
<p>
You're receiving this email because you have exceeded
your limit of {{ limit }} OAR API requests for this month.
</p>
{% endif %}
You're receiving this email because you have used | ||
{{ count }} of your {{ limit }} requests for this month. | ||
|
||
{% if grace_limit %} | ||
The grace limit previously set was {{ grace_limit }}. | ||
{% endif %} |
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.
While testing I realized that we are being more detailed about our limit calculations than we absolutely have to be.
Consider this simplified version that excludes the current count
{% if grace_limit %}
You're receiving this email because you have exceeded your
limit of {{ grace_limit }} OAR API requests for this month.
{% else %}
You're receiving this email because you have exceeded your
limit of {{ limit }} OAR API requests for this month.
{% endif %}
@jwalgran Sincere apologies for way too many fixups! I kept thinking I was done and realizing there were additional changes I should have made. |
Looking at this now. |
I made an incomplete suggestion when I proposed simplifying the emails. The current implementation uses the same email templates for the 90% warning and the limit exceeded notifications. As a result, in my manual testing, when my test user reached 90%, the email sent said "you have exceeded your limit" The options for handling this that I can think of are:
I lean slightly toward using different templates. In general, "dumb" templates are easier to maintain. |
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.
The changes look good and I successfully tested the creation of ApiBlocks and limit and grace_limit emails.
The only remaining issue that I can see is the one that I commented on previously. We need to distinguish between limit warning and limit exceeded emails.
@jwalgran I updated to a second set of templates. The text in them is, "You're receiving this email because you have used 90% of your limit of {{ limit }} OAR API requests for this month." and the subject says "Open Apparel Registry API limit warning." Does this text seem clear for users? |
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.
Confirmed the new templates. We will likely get updated text from the OAR team so the existing text is a good starting point. Thanks.
e3e2a47
to
b4086ea
Compare
b4086ea
to
91e66b0
Compare
Overview
Creates a management command to:
Connects #1139
Demo
Testing Instructions
./scripts/update
./scripts/manage check_api_limits
. Nothing should happen../scripts/manage shell_plus
to create a RequestLog for the contributor, setting the date within the current month the response code in the 200s../scripts/manage check_api_limits
. Nothing should happen../scripts/manage check_api_limits
. You should see an email printed to the console. Check the ContributorNotifications for the user; the api_limit_warning_sent_on should equal the current date../scripts/manage check_api_limits
again. Nothing should happen../scripts/manage check_api_limits
. You should see an email printed to the console. Check the ContributorNotifications for the user; the api_limit_exceeded_sent_on should equal the current date../scripts/manage check_api_limits
. Nothing should happen../scripts/manage check_api_limits
. Nothing should happen../scripts/manage check_api_limits
. Nothing should happen. You should see an email printed to the console. Check the ContributorNotifications for the user; the api_grace_limit_exceeded_sent_on should equal the current date. The ApiBlock should be active again../scripts/manage check_api_limits
. Nothing should happen../scripts/test
. All tests should pass.Checklist
fixup!
commits have been squashed