soft_deactivate: Handle multiple SUBSCRIPTION_DEACTIVATEDs.

Race conditions in stream unsubscription may lead to multiple
back-to-back SUBSCRIPTION_DEACTIVATED RealmAuditLog entries for the
same stream.  The current logic constructs duplicate UserMessage
entries for such, which then later fail to insert.

Keep a set of message-ids that have been prep'd to be inserted, so
that we don't duplicate them if there is a duplicated
SUBSCRIPTION_DEACTIVATED row.  This also renames the `message` local
variable, which otherwise overrode the `message` argument of a
different type.

(cherry picked from commit 6b6dcf6ce1)
This commit is contained in:
Alex Vandiver
2021-11-10 11:37:51 -08:00
parent c05bbd0fd4
commit eadefdf2f5

View File

@@ -1,7 +1,7 @@
# Documented in https://zulip.readthedocs.io/en/latest/subsystems/sending-messages.html#soft-deactivation
import logging
from collections import defaultdict
from typing import Any, DefaultDict, Dict, List, Optional, Union
from typing import Any, DefaultDict, Dict, List, Optional, Set, Union
from django.conf import settings
from django.db import transaction
@@ -32,10 +32,13 @@ def filter_by_subscription_history(
all_stream_subscription_logs: DefaultDict[int, List[RealmAuditLog]],
) -> List[UserMessage]:
user_messages_to_insert: List[UserMessage] = []
seen_message_ids: Set[int] = set()
def store_user_message_to_insert(message: Message) -> None:
message = UserMessage(user_profile=user_profile, message_id=message["id"], flags=0)
user_messages_to_insert.append(message)
if message["id"] not in seen_message_ids:
user_message = UserMessage(user_profile=user_profile, message_id=message["id"], flags=0)
user_messages_to_insert.append(user_message)
seen_message_ids.add(message["id"])
for (stream_id, stream_messages_raw) in all_stream_messages.items():
stream_subscription_logs = all_stream_subscription_logs[stream_id]