models: Create MissedMessageEmailEntry table.

This will be used to store the missedmessage events received
during the waiting time for email notifications (which is currently
2 minutes, hardcoded).

The change in `test_retention` is because we've set `on_delete=CASCADE`
for the message field this table.
The new query is like so:
```
DELETE FROM "zerver_missedmessageemailentry"
    WHERE "zerver_missedmessageemailentry"."message_id" IN (
        1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553
        )
```
This commit is contained in:
Abhijeet Prasad Bodas
2021-07-07 20:25:25 +05:30
committed by Tim Abbott
parent c3319a5231
commit 1709428cff
4 changed files with 89 additions and 1 deletions

View File

@@ -146,6 +146,7 @@ ALL_ZULIP_TABLES = {
"zerver_scheduledemail",
"zerver_scheduledemail_users",
"zerver_scheduledmessage",
"zerver_scheduledmessagenotificationemail",
"zerver_service",
"zerver_stream",
"zerver_submessage",
@@ -182,6 +183,8 @@ NON_EXPORTED_TABLES = {
# missed-message email addresses include the server's hostname and
# expire after a few days.
"zerver_missedmessageemailaddress",
# Scheduled message notification email data is for internal use by the server.
"zerver_scheduledmessagenotificationemail",
# When switching servers, clients will need to re-log in and
# reregister for push notifications anyway.
"zerver_pushdevicetoken",

View File

@@ -0,0 +1,58 @@
# Generated by Django 3.2.5 on 2021-07-09 11:08
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0330_linkifier_pattern_validator"),
]
operations = [
migrations.CreateModel(
name="ScheduledMessageNotificationEmail",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"trigger",
models.TextField(
choices=[
("private_message", "Private message"),
("mentioned", "Mention"),
("wildcard_mentioned", "Wildcard mention"),
("stream_email_notify", "Stream notifications enabled"),
]
),
),
("scheduled_timestamp", models.DateTimeField(db_index=True)),
(
"mentioned_user_group",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zerver.usergroup",
),
),
(
"message",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.message"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
]

View File

@@ -3340,6 +3340,33 @@ class NotificationTriggers:
STREAM_EMAIL = "stream_email_notify"
class ScheduledMessageNotificationEmail(models.Model):
"""Stores planned outgoing message notification emails. They may be
processed earlier should Zulip choose to batch multiple messages
in a single email, but typically will be processed just after
scheduled_timestamp.
"""
user_profile: UserProfile = models.ForeignKey(UserProfile, on_delete=CASCADE)
message: Message = models.ForeignKey(Message, on_delete=CASCADE)
EMAIL_NOTIFICATION_TRIGGER_CHOICES = [
(NotificationTriggers.PRIVATE_MESSAGE, "Private message"),
(NotificationTriggers.MENTION, "Mention"),
(NotificationTriggers.WILDCARD_MENTION, "Wildcard mention"),
(NotificationTriggers.STREAM_EMAIL, "Stream notifications enabled"),
]
trigger: str = models.TextField(choices=EMAIL_NOTIFICATION_TRIGGER_CHOICES)
mentioned_user_group: Optional[UserGroup] = models.ForeignKey(
UserGroup, null=True, on_delete=CASCADE
)
# Timestamp for when the notification should be processed and sent.
# Calculated from the time the event was received and the batching period.
scheduled_timestamp: datetime.datetime = models.DateTimeField(db_index=True)
class ScheduledMessage(models.Model):
id: int = models.AutoField(auto_created=True, primary_key=True, verbose_name="ID")
sender: UserProfile = models.ForeignKey(UserProfile, on_delete=CASCADE)

View File

@@ -1056,7 +1056,7 @@ class TestDoDeleteMessages(ZulipTestCase):
with queries_captured() as queries:
do_delete_messages(realm, messages)
self.assertFalse(Message.objects.filter(id__in=message_ids).exists())
self.assert_length(queries, 18)
self.assert_length(queries, 19)
archived_messages = ArchivedMessage.objects.filter(id__in=message_ids)
self.assertEqual(archived_messages.count(), len(message_ids))