-
Notifications
You must be signed in to change notification settings - Fork 41
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
[feat] Batch email notifications #276
base: gsoc24
Are you sure you want to change the base?
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.
@Dhanus3133 I have left some suggestions. I hope these solve your queries.
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.
@Dhanus3133 please start writin a short README section that explains how this feature works and add the new setting, remember to add a screenshot (push it to the docs branch).
@pandafy you know what would be handy?
- Allow to change the batching using an organization setting that allows user to change this per org via the admin
- Allow to specify whether the system should start batching right away instead of waiting 1 email, this could be disabled by default, and could also be available from the organization page
|
||
# Check if the rest of the notifications are sent in a batch | ||
self.assertEqual(len(mail.outbox), 2) | ||
self.assertEqual(mail.outbox[1].subject, "Summary of Notifications") |
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'd try to explore the possibility of using freezegun to simulate the passing of time and ensure that a new notification sent after the batch interval is not batched.
In our weekly call, @nemesifier and @pandafy suggested some improvements.
|
7736e9d
to
4abc717
Compare
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.
This is looking good. I have done a quick code review and left some suggestion on improving the code.
I will do a functional test tomorrow and report if I find something to improve.
openwisp_notifications/settings.py
Outdated
@@ -37,6 +37,10 @@ | |||
'openwisp-notifications/audio/notification_bell.mp3', | |||
) | |||
|
|||
OPENWISP_NOTIFICATIONS_EMAIL_BATCH_INTERVAL = getattr( | |||
settings, 'EMAIL_BATCH_INTERVAL', 30 * 60 # 30 minutes |
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.
Thinking out loud
I think 30 minutes is a lot of time. It will affect the real-timeness of the email notifications. Most of the consecutive notifications would be delayed by this time. We should also point this out in the README.
@nemesifier what do you think?
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.
Immediate email after batch email
If a notification is created just after the batch email is processed, then the email for this notification is sent immediately after the batch email.
Is this a desired behaviour? Can you please add a test for this?
Duplicate subject in email
The send_email function adds a subject in the email which servers as a heading for all the email communication.
I think, we should keep using the subject provided by the send_email
function for consistency.
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.
@Dhanus3133 the test is failing because the notification email contains direct URL to the target object while the test expects redirect url
-<div class="msg"><p>Default notification with default verb and level info by <a href="https://example.com/api/v1/notifications/notification/2632e308-0f2d-43a1-8617-7350e48b8fd3/redirect/">Tester Tester (test org)</a></p></div>
+<div class="msg"><p>Default notification with default verb and level info by <a href="https://example.com/admin/openwisp_users/organizationuser/dea5c3cc-8c2a-4021-94a7-9cc36885f9ff/change/">Tester Tester (test org)</a></p></div>
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.
Great work @Dhanus3133 @pandafy, see my comments below.
@@ -1013,6 +1013,19 @@ The default configuration is as follows: | |||
'max_allowed_backoff': 15, | |||
} | |||
``OPENWISP_NOTIFICATIONS_EMAIL_BATCH_INTERVAL`` | |||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
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.
This seems longer than it should
# Case 2: Single email sending logic | ||
# Update the last email sent time and cache the data | ||
cache_data['last_email_sent_time'] = timezone.now() | ||
cache.set(cache_key, cache_data, timeout=EMAIL_BATCH_INTERVAL) |
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 EMAIL_BATCH_INTERVAL
is zero, wouldn't this data be cached indefinitely? If that's the case, it's a problem.
|
||
|
||
@shared_task(base=OpenwispCeleryTask) | ||
def batch_email_notification(instance_id): |
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 am not convinced of the name of this function here.
Does this function batch emails, or does it send batched emails? From the name it seems it does the former, but from the code it seems to me it does the latter. Please clarify.
If it's the latter, we should rename it to something like send_batched_email_notifications
or something similar.
@@ -37,6 +37,10 @@ | |||
'openwisp-notifications/audio/notification_bell.mp3', | |||
) | |||
|
|||
OPENWISP_NOTIFICATIONS_EMAIL_BATCH_INTERVAL = getattr( |
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.
Let's shorten this, we usually do this in most modules, eg:
OPENWISP_NOTIFICATIONS_EMAIL_BATCH_INTERVAL = getattr( | |
EMAIL_BATCH_INTERVAL = getattr( |
plain_text_content = render_to_string('emails/batch_email.txt', context) | ||
|
||
extra_context = {} | ||
if notifications_count > 5: |
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.
are we showing only 5 notifications? Let's show more and make this configurable with a setting, eg: OPENWISP_NOTIFICATIONS_EMAIL_BATCH_DISPLAY_LIMIT
(add to README). I think we can default this to 15.
@@ -0,0 +1,15 @@ | |||
Summary of {{ notifications_count }} Notifications from {{ site_name }} |
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.
Flag all strings as translatable using translate
and blocktranslate
: https://docs.djangoproject.com/en/5.0/topics/i18n/translation/#internationalization-in-template-code
Also here let's change this sentence as for the change I recommended in the subject, let's maintain consistency, eg: "{notifications_count} new notifications since <UTC_DATE_AND_TIME>".
|
||
|
||
def send_notification_email(notification): | ||
|
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.
can we remove this blank line or does black
complain about it?
notification = unsent_notifications.first() | ||
send_notification_email(notification) | ||
else: | ||
# Show notification description upto 5 notifications |
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.
# Show notification description upto 5 notifications | |
# Show the amount of notifications according to configured display limit |
send_notification_email(notification) | ||
else: | ||
# Show notification description upto 5 notifications | ||
show_notification_description = notifications_count <= 5 |
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.
use setting instead of hardcoding 5
self.assertIn('Summary of 10 Notifications', mail.outbox[1].subject) | ||
self.assertIn('View all Notifications', mail.outbox[1].body) | ||
self.assertNotIn('Test Notification', mail.outbox[1].body) | ||
|
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.
Can we add another test in which this feature is disabled and ensure that no batching happens in that case?
Using the override_settings
from django or mocking the setting should work.
Fixes #132