django_api: Extract send_event_on_commit helper.

django-stubs 4.2.1 gives transaction.on_commit a more accurate type
annotation, but this exposed that mypy can’t handle the lambda default
parameters that we use to recapture loop variables such as

    for stream_id in public_stream_ids:
        peer_user_ids = …
        event = …

        transaction.on_commit(
            lambda event=event, peer_user_ids=peer_user_ids: send_event(
                realm, event, peer_user_ids
            )
        )

https://github.com/python/mypy/issues/15459

A workaround that mypy accepts is

        transaction.on_commit(
            (
                lambda event, peer_user_ids: lambda: send_event(
                    realm, event, peer_user_ids
                )
            )(event, peer_user_ids)
        )

But that’s kind of ugly and potentially error-prone, so let’s make a
helper function for this very common pattern.

        send_event_on_commit(realm, event, peer_user_ids)

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2023-06-17 11:53:07 -07:00
committed by Tim Abbott
parent 77c146b8b0
commit 7657cb4a0f
22 changed files with 114 additions and 180 deletions

View File

@@ -6,7 +6,7 @@ from django.utils.timezone import now as timezone_now
from zerver.actions.create_user import created_bot_event from zerver.actions.create_user import created_bot_event
from zerver.models import RealmAuditLog, Stream, UserProfile, active_user_ids, bot_owner_user_ids from zerver.models import RealmAuditLog, Stream, UserProfile, active_user_ids, bot_owner_user_ids
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -41,12 +41,10 @@ def do_change_bot_owner(
), ),
) )
previous_owner_id = previous_owner.id previous_owner_id = previous_owner.id
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, delete_event,
delete_event, {previous_owner_id},
{previous_owner_id},
)
) )
# Do not send update event for previous bot owner. # Do not send update event for previous bot owner.
update_users = update_users - {previous_owner.id} update_users = update_users - {previous_owner.id}
@@ -54,7 +52,7 @@ def do_change_bot_owner(
# Notify the new owner that the bot has been added. # Notify the new owner that the bot has been added.
if not bot_owner.is_realm_admin: if not bot_owner.is_realm_admin:
add_event = created_bot_event(user_profile) add_event = created_bot_event(user_profile)
transaction.on_commit(lambda: send_event(user_profile.realm, add_event, {bot_owner.id})) send_event_on_commit(user_profile.realm, add_event, {bot_owner.id})
# Do not send update event for bot_owner. # Do not send update event for bot_owner.
update_users = update_users - {bot_owner.id} update_users = update_users - {bot_owner.id}
@@ -66,12 +64,10 @@ def do_change_bot_owner(
owner_id=user_profile.bot_owner.id, owner_id=user_profile.bot_owner.id,
), ),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, bot_event,
bot_event, update_users,
update_users,
)
) )
# Since `bot_owner_id` is included in the user profile dict we need # Since `bot_owner_id` is included in the user profile dict we need
@@ -84,9 +80,7 @@ def do_change_bot_owner(
bot_owner_id=user_profile.bot_owner.id, bot_owner_id=user_profile.bot_owner.id,
), ),
) )
transaction.on_commit( send_event_on_commit(user_profile.realm, event, active_user_ids(user_profile.realm_id))
lambda: send_event(user_profile.realm, event, active_user_ids(user_profile.realm_id))
)
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -125,12 +119,10 @@ def do_change_default_sending_stream(
default_sending_stream=stream_name, default_sending_stream=stream_name,
), ),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, event,
event, bot_owner_user_ids(user_profile),
bot_owner_user_ids(user_profile),
)
) )
@@ -171,12 +163,10 @@ def do_change_default_events_register_stream(
default_events_register_stream=stream_name, default_events_register_stream=stream_name,
), ),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, event,
event, bot_owner_user_ids(user_profile),
bot_owner_user_ids(user_profile),
)
) )
@@ -212,10 +202,8 @@ def do_change_default_all_public_streams(
default_all_public_streams=user_profile.default_all_public_streams, default_all_public_streams=user_profile.default_all_public_streams,
), ),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, event,
event, bot_owner_user_ids(user_profile),
bot_owner_user_ids(user_profile),
)
) )

View File

@@ -48,7 +48,7 @@ from zerver.models import (
bot_owner_user_ids, bot_owner_user_ids,
get_system_bot, get_system_bot,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
if settings.BILLING_ENABLED: if settings.BILLING_ENABLED:
from corporate.lib.stripe import update_license_ledger_if_needed from corporate.lib.stripe import update_license_ledger_if_needed
@@ -311,20 +311,12 @@ def notify_created_user(user_profile: UserProfile) -> None:
event: Dict[str, Any] = dict( event: Dict[str, Any] = dict(
type="realm_user", op="add", person=person_for_real_email_access_users type="realm_user", op="add", person=person_for_real_email_access_users
) )
transaction.on_commit( send_event_on_commit(user_profile.realm, event, user_ids_with_real_email_access)
lambda event=event: send_event(
user_profile.realm, event, user_ids_with_real_email_access
)
)
if user_ids_without_real_email_access: if user_ids_without_real_email_access:
assert person_for_without_real_email_access_users is not None assert person_for_without_real_email_access_users is not None
event = dict(type="realm_user", op="add", person=person_for_without_real_email_access_users) event = dict(type="realm_user", op="add", person=person_for_without_real_email_access_users)
transaction.on_commit( send_event_on_commit(user_profile.realm, event, user_ids_without_real_email_access)
lambda event=event: send_event(
user_profile.realm, event, user_ids_without_real_email_access
)
)
def created_bot_event(user_profile: UserProfile) -> Dict[str, Any]: def created_bot_event(user_profile: UserProfile) -> Dict[str, Any]:
@@ -361,9 +353,7 @@ def created_bot_event(user_profile: UserProfile) -> Dict[str, Any]:
def notify_created_bot(user_profile: UserProfile) -> None: def notify_created_bot(user_profile: UserProfile) -> None:
event = created_bot_event(user_profile) event = created_bot_event(user_profile)
transaction.on_commit( send_event_on_commit(user_profile.realm, event, bot_owner_user_ids(user_profile))
lambda: send_event(user_profile.realm, event, bot_owner_user_ids(user_profile))
)
def do_create_user( def do_create_user(

View File

@@ -13,7 +13,7 @@ from zerver.models import (
active_non_guest_user_ids, active_non_guest_user_ids,
get_default_stream_groups, get_default_stream_groups,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def check_default_stream_group_name(group_name: str) -> None: def check_default_stream_group_name(group_name: str) -> None:
@@ -52,7 +52,7 @@ def notify_default_streams(realm: Realm) -> None:
type="default_streams", type="default_streams",
default_streams=streams_to_dicts_sorted(get_default_streams_for_realm(realm.id)), default_streams=streams_to_dicts_sorted(get_default_streams_for_realm(realm.id)),
) )
transaction.on_commit(lambda: send_event(realm, event, active_non_guest_user_ids(realm.id))) send_event_on_commit(realm, event, active_non_guest_user_ids(realm.id))
def notify_default_stream_groups(realm: Realm) -> None: def notify_default_stream_groups(realm: Realm) -> None:
@@ -62,7 +62,7 @@ def notify_default_stream_groups(realm: Realm) -> None:
get_default_stream_groups(realm) get_default_stream_groups(realm)
), ),
) )
transaction.on_commit(lambda: send_event(realm, event, active_non_guest_user_ids(realm.id))) send_event_on_commit(realm, event, active_non_guest_user_ids(realm.id))
def do_add_default_stream(stream: Stream) -> None: def do_add_default_stream(stream: Stream) -> None:

View File

@@ -1,12 +1,10 @@
from typing import Iterable, List, TypedDict from typing import Iterable, List, TypedDict
from django.db import transaction
from zerver.lib import retention from zerver.lib import retention
from zerver.lib.retention import move_messages_to_archive from zerver.lib.retention import move_messages_to_archive
from zerver.lib.stream_subscription import get_active_subscriptions_for_stream_id from zerver.lib.stream_subscription import get_active_subscriptions_for_stream_id
from zerver.models import Message, Realm, UserMessage, UserProfile from zerver.models import Message, Realm, UserMessage, UserProfile
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
class DeleteMessagesEvent(TypedDict, total=False): class DeleteMessagesEvent(TypedDict, total=False):
@@ -56,7 +54,7 @@ def do_delete_messages(realm: Realm, messages: Iterable[Message]) -> None:
move_messages_to_archive(message_ids, realm=realm, chunk_size=archiving_chunk_size) move_messages_to_archive(message_ids, realm=realm, chunk_size=archiving_chunk_size)
event["message_type"] = message_type event["message_type"] = message_type
transaction.on_commit(lambda: send_event(realm, event, users_to_notify)) send_event_on_commit(realm, event, users_to_notify)
def do_delete_messages_by_sender(user: UserProfile) -> None: def do_delete_messages_by_sender(user: UserProfile) -> None:

View File

@@ -1,6 +1,5 @@
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
from django.db import transaction
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from zerver.actions.create_user import create_historical_user_messages from zerver.actions.create_user import create_historical_user_messages
@@ -9,7 +8,7 @@ from zerver.lib.exceptions import JsonableError
from zerver.lib.message import access_message, update_to_dict_cache from zerver.lib.message import access_message, update_to_dict_cache
from zerver.lib.stream_subscription import subscriber_ids_with_stream_history_access from zerver.lib.stream_subscription import subscriber_ids_with_stream_history_access
from zerver.models import Message, Reaction, Recipient, Stream, UserMessage, UserProfile from zerver.models import Message, Reaction, Recipient, Stream, UserMessage, UserProfile
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def notify_reaction_update( def notify_reaction_update(
@@ -60,7 +59,7 @@ def notify_reaction_update(
stream = Stream.objects.get(id=stream_id) stream = Stream.objects.get(id=stream_id)
user_ids |= subscriber_ids_with_stream_history_access(stream) user_ids |= subscriber_ids_with_stream_history_access(stream)
transaction.on_commit(lambda: send_event(user_profile.realm, event, list(user_ids))) send_event_on_commit(user_profile.realm, event, list(user_ids))
def do_add_reaction( def do_add_reaction(

View File

@@ -14,7 +14,7 @@ from zerver.models import (
active_user_ids, active_user_ids,
get_realm_domains, get_realm_domains,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -46,7 +46,7 @@ def do_add_realm_domain(
domain=realm_domain.domain, allow_subdomains=realm_domain.allow_subdomains domain=realm_domain.domain, allow_subdomains=realm_domain.allow_subdomains
), ),
) )
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
return realm_domain return realm_domain
@@ -82,9 +82,7 @@ def do_change_realm_domain(
domain=realm_domain.domain, allow_subdomains=realm_domain.allow_subdomains domain=realm_domain.domain, allow_subdomains=realm_domain.allow_subdomains
), ),
) )
transaction.on_commit( send_event_on_commit(realm_domain.realm, event, active_user_ids(realm_domain.realm_id))
lambda: send_event(realm_domain.realm, event, active_user_ids(realm_domain.realm_id))
)
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -119,4 +117,4 @@ def do_remove_realm_domain(
# confusing than the alternative. # confusing than the alternative.
do_set_realm_property(realm, "emails_restricted_to_domains", False, acting_user=acting_user) do_set_realm_property(realm, "emails_restricted_to_domains", False, acting_user=acting_user)
event = dict(type="realm_domains", op="remove", domain=domain) event = dict(type="realm_domains", op="remove", domain=domain)
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))

View File

@@ -12,12 +12,12 @@ from zerver.lib.exceptions import JsonableError
from zerver.lib.pysa import mark_sanitized from zerver.lib.pysa import mark_sanitized
from zerver.lib.upload import upload_emoji_image from zerver.lib.upload import upload_emoji_image
from zerver.models import EmojiInfo, Realm, RealmAuditLog, RealmEmoji, UserProfile, active_user_ids from zerver.models import EmojiInfo, Realm, RealmAuditLog, RealmEmoji, UserProfile, active_user_ids
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def notify_realm_emoji(realm: Realm, realm_emoji: Dict[str, EmojiInfo]) -> None: def notify_realm_emoji(realm: Realm, realm_emoji: Dict[str, EmojiInfo]) -> None:
event = dict(type="realm_emoji", op="update", realm_emoji=realm_emoji) event = dict(type="realm_emoji", op="update", realm_emoji=realm_emoji)
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
def check_add_realm_emoji( def check_add_realm_emoji(

View File

@@ -1,17 +1,16 @@
import orjson import orjson
from django.db import transaction
from django.utils.timezone import now as timezone_now from django.utils.timezone import now as timezone_now
from zerver.lib.export import get_realm_exports_serialized from zerver.lib.export import get_realm_exports_serialized
from zerver.lib.upload import delete_export_tarball from zerver.lib.upload import delete_export_tarball
from zerver.models import RealmAuditLog, UserProfile from zerver.models import RealmAuditLog, UserProfile
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def notify_realm_export(user_profile: UserProfile) -> None: def notify_realm_export(user_profile: UserProfile) -> None:
# In the future, we may want to send this event to all realm admins. # In the future, we may want to send this event to all realm admins.
event = dict(type="realm_export", exports=get_realm_exports_serialized(user_profile)) event = dict(type="realm_export", exports=get_realm_exports_serialized(user_profile))
transaction.on_commit(lambda: send_event(user_profile.realm, event, [user_profile.id])) send_event_on_commit(user_profile.realm, event, [user_profile.id])
def do_delete_realm_export(user_profile: UserProfile, export: RealmAuditLog) -> None: def do_delete_realm_export(user_profile: UserProfile, export: RealmAuditLog) -> None:

View File

@@ -5,7 +5,7 @@ from django.utils.timezone import now as timezone_now
from zerver.lib.realm_icon import realm_icon_url from zerver.lib.realm_icon import realm_icon_url
from zerver.models import Realm, RealmAuditLog, UserProfile, active_user_ids from zerver.models import Realm, RealmAuditLog, UserProfile, active_user_ids
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -31,10 +31,8 @@ def do_change_icon_source(
property="icon", property="icon",
data=dict(icon_source=realm.icon_source, icon_url=realm_icon_url(realm)), data=dict(icon_source=realm.icon_source, icon_url=realm_icon_url(realm)),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( realm,
realm, event,
event, active_user_ids(realm.id),
active_user_ids(realm.id),
)
) )

View File

@@ -13,12 +13,12 @@ from zerver.models import (
active_user_ids, active_user_ids,
linkifiers_for_realm, linkifiers_for_realm,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def notify_linkifiers(realm: Realm, realm_linkifiers: List[LinkifierDict]) -> None: def notify_linkifiers(realm: Realm, realm_linkifiers: List[LinkifierDict]) -> None:
event: Dict[str, object] = dict(type="realm_linkifiers", realm_linkifiers=realm_linkifiers) event: Dict[str, object] = dict(type="realm_linkifiers", realm_linkifiers=realm_linkifiers)
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
# NOTE: Regexes must be simple enough that they can be easily translated to JavaScript # NOTE: Regexes must be simple enough that they can be easily translated to JavaScript

View File

@@ -5,7 +5,7 @@ from django.utils.timezone import now as timezone_now
from zerver.lib.realm_logo import get_realm_logo_data from zerver.lib.realm_logo import get_realm_logo_data
from zerver.models import Realm, RealmAuditLog, UserProfile, active_user_ids from zerver.models import Realm, RealmAuditLog, UserProfile, active_user_ids
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
@transaction.atomic(durable=True) @transaction.atomic(durable=True)
@@ -35,4 +35,4 @@ def do_change_logo_source(
property="night_logo" if night else "logo", property="night_logo" if night else "logo",
data=get_realm_logo_data(realm, night), data=get_realm_logo_data(realm, night),
) )
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))

View File

@@ -13,12 +13,12 @@ from zerver.models import (
active_user_ids, active_user_ids,
get_realm_playgrounds, get_realm_playgrounds,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def notify_realm_playgrounds(realm: Realm, realm_playgrounds: List[RealmPlaygroundDict]) -> None: def notify_realm_playgrounds(realm: Realm, realm_playgrounds: List[RealmPlaygroundDict]) -> None:
event = dict(type="realm_playgrounds", realm_playgrounds=realm_playgrounds) event = dict(type="realm_playgrounds", realm_playgrounds=realm_playgrounds)
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
@transaction.atomic(durable=True) @transaction.atomic(durable=True)

View File

@@ -36,7 +36,7 @@ from zerver.models import (
active_user_ids, active_user_ids,
get_realm, get_realm,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event, send_event_on_commit
if settings.BILLING_ENABLED: if settings.BILLING_ENABLED:
from corporate.lib.stripe import downgrade_now_without_creating_additional_invoices from corporate.lib.stripe import downgrade_now_without_creating_additional_invoices
@@ -83,7 +83,7 @@ def do_set_realm_property(
data={name: value}, data={name: value},
) )
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
event_time = timezone_now() event_time = timezone_now()
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
@@ -435,7 +435,7 @@ def do_change_realm_org_type(
) )
event = dict(type="realm", op="update", property="org_type", value=org_type) event = dict(type="realm", op="update", property="org_type", value=org_type)
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
@transaction.atomic(savepoint=False) @transaction.atomic(savepoint=False)
@@ -499,7 +499,7 @@ def do_change_realm_plan_type(
"value": plan_type, "value": plan_type,
"extra_data": {"upload_quota": realm.upload_quota_bytes()}, "extra_data": {"upload_quota": realm.upload_quota_bytes()},
} }
transaction.on_commit(lambda: send_event(realm, event, active_user_ids(realm.id))) send_event_on_commit(realm, event, active_user_ids(realm.id))
def do_send_realm_reactivation_email(realm: Realm, *, acting_user: Optional[UserProfile]) -> None: def do_send_realm_reactivation_email(realm: Realm, *, acting_user: Optional[UserProfile]) -> None:

View File

@@ -64,7 +64,7 @@ from zerver.models import (
active_non_guest_user_ids, active_non_guest_user_ids,
get_system_bot, get_system_bot,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event, send_event_on_commit
@transaction.atomic(savepoint=False) @transaction.atomic(savepoint=False)
@@ -127,7 +127,7 @@ def do_deactivate_stream(
stream_dict = stream.to_dict() stream_dict = stream.to_dict()
stream_dict.update(dict(name=old_name, invite_only=was_invite_only)) stream_dict.update(dict(name=old_name, invite_only=was_invite_only))
event = dict(type="stream", op="delete", streams=[stream_dict]) event = dict(type="stream", op="delete", streams=[stream_dict])
transaction.on_commit(lambda: send_event(stream.realm, event, affected_user_ids)) send_event_on_commit(stream.realm, event, affected_user_ids)
event_time = timezone_now() event_time = timezone_now()
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
@@ -403,11 +403,7 @@ def send_peer_subscriber_events(
stream_ids=[stream_id], stream_ids=[stream_id],
user_ids=sorted(altered_user_ids), user_ids=sorted(altered_user_ids),
) )
transaction.on_commit( send_event_on_commit(realm, event, peer_user_ids)
lambda event=event, peer_user_ids=peer_user_ids: send_event(
realm, event, peer_user_ids
)
)
public_stream_ids = [ public_stream_ids = [
stream_id stream_id
@@ -445,11 +441,7 @@ def send_peer_subscriber_events(
stream_ids=[stream_id], stream_ids=[stream_id],
user_ids=sorted(altered_user_ids), user_ids=sorted(altered_user_ids),
) )
transaction.on_commit( send_event_on_commit(realm, event, peer_user_ids)
lambda event=event, peer_user_ids=peer_user_ids: send_event(
realm, event, peer_user_ids
)
)
for user_id, stream_ids in user_streams.items(): for user_id, stream_ids in user_streams.items():
peer_user_ids = public_peer_ids - {user_id} peer_user_ids = public_peer_ids - {user_id}
@@ -459,11 +451,7 @@ def send_peer_subscriber_events(
stream_ids=sorted(stream_ids), stream_ids=sorted(stream_ids),
user_ids=[user_id], user_ids=[user_id],
) )
transaction.on_commit( send_event_on_commit(realm, event, peer_user_ids)
lambda event=event, peer_user_ids=peer_user_ids: send_event(
realm, event, peer_user_ids
)
)
SubT = Tuple[List[SubInfo], List[SubInfo]] SubT = Tuple[List[SubInfo], List[SubInfo]]
@@ -1359,6 +1347,4 @@ def do_change_stream_group_based_setting(
stream_id=stream.id, stream_id=stream.id,
name=stream.name, name=stream.name,
) )
transaction.on_commit( send_event_on_commit(stream.realm, event, can_access_stream_user_ids(stream))
lambda: send_event(stream.realm, event, can_access_stream_user_ids(stream))
)

View File

@@ -1,9 +1,8 @@
from django.db import transaction
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from zerver.lib.exceptions import JsonableError from zerver.lib.exceptions import JsonableError
from zerver.models import Realm, SubMessage, UserMessage from zerver.models import Realm, SubMessage, UserMessage
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event_on_commit
def verify_submessage_sender( def verify_submessage_sender(
@@ -60,4 +59,4 @@ def do_add_submessage(
ums = UserMessage.objects.filter(message_id=message_id) ums = UserMessage.objects.filter(message_id=message_id)
target_user_ids = [um.user_profile_id for um in ums] target_user_ids = [um.user_profile_id for um in ums]
transaction.on_commit(lambda: send_event(realm, event, target_user_ids)) send_event_on_commit(realm, event, target_user_ids)

View File

@@ -16,7 +16,7 @@ from zerver.models import (
UserProfile, UserProfile,
active_user_ids, active_user_ids,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event, send_event_on_commit
class MemberGroupUserDict(TypedDict): class MemberGroupUserDict(TypedDict):
@@ -181,9 +181,7 @@ def do_send_user_group_members_update_event(
event_name: str, user_group: UserGroup, user_ids: List[int] event_name: str, user_group: UserGroup, user_ids: List[int]
) -> None: ) -> None:
event = dict(type="user_group", op=event_name, group_id=user_group.id, user_ids=user_ids) event = dict(type="user_group", op=event_name, group_id=user_group.id, user_ids=user_ids)
transaction.on_commit( send_event_on_commit(user_group.realm, event, active_user_ids(user_group.realm_id))
lambda: send_event(user_group.realm, event, active_user_ids(user_group.realm_id))
)
@transaction.atomic(savepoint=False) @transaction.atomic(savepoint=False)
@@ -216,9 +214,7 @@ def do_send_subgroups_update_event(
event = dict( event = dict(
type="user_group", op=event_name, group_id=user_group.id, direct_subgroup_ids=subgroup_ids type="user_group", op=event_name, group_id=user_group.id, direct_subgroup_ids=subgroup_ids
) )
transaction.on_commit( send_event_on_commit(user_group.realm, event, active_user_ids(user_group.realm_id))
lambda: send_event(user_group.realm, event, active_user_ids(user_group.realm_id))
)
@transaction.atomic @transaction.atomic

View File

@@ -42,18 +42,16 @@ from zerver.models import (
get_client, get_client,
get_user_profile_by_id, get_user_profile_by_id,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event, send_event_on_commit
def send_user_email_update_event(user_profile: UserProfile) -> None: def send_user_email_update_event(user_profile: UserProfile) -> None:
payload = dict(user_id=user_profile.id, new_email=user_profile.email) payload = dict(user_id=user_profile.id, new_email=user_profile.email)
event = dict(type="realm_user", op="update", person=payload) event = dict(type="realm_user", op="update", person=payload)
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, event,
event, active_user_ids(user_profile.realm_id),
active_user_ids(user_profile.realm_id),
)
) )
@@ -81,22 +79,18 @@ def send_delivery_email_update_events(
if delivery_email_now_visible_user_ids: if delivery_email_now_visible_user_ids:
person = dict(user_id=user_profile.id, delivery_email=user_profile.delivery_email) person = dict(user_id=user_profile.id, delivery_email=user_profile.delivery_email)
event = dict(type="realm_user", op="update", person=person) event = dict(type="realm_user", op="update", person=person)
transaction.on_commit( send_event_on_commit(
lambda event=event: send_event( user_profile.realm,
user_profile.realm, event,
event, delivery_email_now_visible_user_ids,
delivery_email_now_visible_user_ids,
)
) )
if delivery_email_now_invisible_user_ids: if delivery_email_now_invisible_user_ids:
person = dict(user_id=user_profile.id, delivery_email=None) person = dict(user_id=user_profile.id, delivery_email=None)
event = dict(type="realm_user", op="update", person=person) event = dict(type="realm_user", op="update", person=person)
transaction.on_commit( send_event_on_commit(
lambda event=event: send_event( user_profile.realm,
user_profile.realm, event,
event, delivery_email_now_invisible_user_ids,
delivery_email_now_invisible_user_ids,
)
) )
@@ -116,9 +110,7 @@ def do_change_user_delivery_email(user_profile: UserProfile, new_email: str) ->
event = dict(type="realm_user", op="update", person=payload) event = dict(type="realm_user", op="update", person=payload)
delivery_email_visible_user_ids = get_users_with_access_to_real_email(user_profile) delivery_email_visible_user_ids = get_users_with_access_to_real_email(user_profile)
transaction.on_commit( send_event_on_commit(user_profile.realm, event, delivery_email_visible_user_ids)
lambda: send_event(user_profile.realm, event, delivery_email_visible_user_ids)
)
if user_profile.avatar_source == UserProfile.AVATAR_FROM_GRAVATAR: if user_profile.avatar_source == UserProfile.AVATAR_FROM_GRAVATAR:
# If the user is using Gravatar to manage their email address, # If the user is using Gravatar to manage their email address,
@@ -320,12 +312,10 @@ def notify_avatar_url_change(user_profile: UserProfile) -> None:
avatar_url=avatar_url(user_profile), avatar_url=avatar_url(user_profile),
), ),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, bot_event,
bot_event, bot_owner_user_ids(user_profile),
bot_owner_user_ids(user_profile),
)
) )
payload = dict( payload = dict(
@@ -339,12 +329,10 @@ def notify_avatar_url_change(user_profile: UserProfile) -> None:
) )
event = dict(type="realm_user", op="update", person=payload) event = dict(type="realm_user", op="update", person=payload)
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, event,
event, active_user_ids(user_profile.realm_id),
active_user_ids(user_profile.realm_id),
)
) )
@@ -450,7 +438,7 @@ def do_change_user_setting(
assert isinstance(setting_value, str) assert isinstance(setting_value, str)
event["language_name"] = get_language_name(setting_value) event["language_name"] = get_language_name(setting_value)
transaction.on_commit(lambda: send_event(user_profile.realm, event, [user_profile.id])) send_event_on_commit(user_profile.realm, event, [user_profile.id])
if setting_name in UserProfile.notification_settings_legacy: if setting_name in UserProfile.notification_settings_legacy:
# This legacy event format is for backwards-compatibility with # This legacy event format is for backwards-compatibility with
@@ -462,9 +450,7 @@ def do_change_user_setting(
"notification_name": setting_name, "notification_name": setting_name,
"setting": setting_value, "setting": setting_value,
} }
transaction.on_commit( send_event_on_commit(user_profile.realm, legacy_event, [user_profile.id])
lambda: send_event(user_profile.realm, legacy_event, [user_profile.id])
)
if setting_name in UserProfile.display_settings_legacy or setting_name == "timezone": if setting_name in UserProfile.display_settings_legacy or setting_name == "timezone":
# This legacy event format is for backwards-compatibility with # This legacy event format is for backwards-compatibility with
@@ -480,9 +466,7 @@ def do_change_user_setting(
assert isinstance(setting_value, str) assert isinstance(setting_value, str)
legacy_event["language_name"] = get_language_name(setting_value) legacy_event["language_name"] = get_language_name(setting_value)
transaction.on_commit( send_event_on_commit(user_profile.realm, legacy_event, [user_profile.id])
lambda: send_event(user_profile.realm, legacy_event, [user_profile.id])
)
# Updates to the time zone display setting are sent to all users # Updates to the time zone display setting are sent to all users
if setting_name == "timezone": if setting_name == "timezone":
@@ -492,12 +476,10 @@ def do_change_user_setting(
timezone=canonicalize_timezone(user_profile.timezone), timezone=canonicalize_timezone(user_profile.timezone),
) )
timezone_event = dict(type="realm_user", op="update", person=payload) timezone_event = dict(type="realm_user", op="update", person=payload)
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm,
user_profile.realm, timezone_event,
timezone_event, active_user_ids(user_profile.realm_id),
active_user_ids(user_profile.realm_id),
)
) )
if setting_name == "email_address_visibility": if setting_name == "email_address_visibility":

View File

@@ -39,7 +39,7 @@ from zerver.models import (
get_fake_email_domain, get_fake_email_domain,
get_user_profile_by_id, get_user_profile_by_id,
) )
from zerver.tornado.django_api import send_event from zerver.tornado.django_api import send_event, send_event_on_commit
if settings.BILLING_ENABLED: if settings.BILLING_ENABLED:
from corporate.lib.stripe import update_license_ledger_if_needed from corporate.lib.stripe import update_license_ledger_if_needed
@@ -297,10 +297,8 @@ def do_deactivate_user(
op="remove", op="remove",
person=dict(user_id=user_profile.id, full_name=user_profile.full_name), person=dict(user_id=user_profile.id, full_name=user_profile.full_name),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm, event_remove_user, active_user_ids(user_profile.realm_id)
user_profile.realm, event_remove_user, active_user_ids(user_profile.realm_id)
)
) )
if user_profile.is_bot: if user_profile.is_bot:
@@ -309,10 +307,8 @@ def do_deactivate_user(
op="remove", op="remove",
bot=dict(user_id=user_profile.id, full_name=user_profile.full_name), bot=dict(user_id=user_profile.id, full_name=user_profile.full_name),
) )
transaction.on_commit( send_event_on_commit(
lambda: send_event( user_profile.realm, event_remove_bot, bot_owner_user_ids(user_profile)
user_profile.realm, event_remove_bot, bot_owner_user_ids(user_profile)
)
) )
@@ -342,9 +338,7 @@ def do_change_user_role(
event = dict( event = dict(
type="realm_user", op="update", person=dict(user_id=user_profile.id, role=user_profile.role) type="realm_user", op="update", person=dict(user_id=user_profile.id, role=user_profile.role)
) )
transaction.on_commit( send_event_on_commit(user_profile.realm, event, active_user_ids(user_profile.realm_id))
lambda: send_event(user_profile.realm, event, active_user_ids(user_profile.realm_id))
)
UserGroupMembership.objects.filter( UserGroupMembership.objects.filter(
user_profile=user_profile, user_group=old_system_group user_profile=user_profile, user_group=old_system_group

View File

@@ -4476,7 +4476,7 @@ class DeleteMessageTest(ZulipTestCase):
message = self.get_last_message() message = self.get_last_message()
with self.capture_send_event_calls(expected_num_events=1): with self.capture_send_event_calls(expected_num_events=1):
with mock.patch("zerver.actions.message_edit.send_event") as m: with mock.patch("zerver.tornado.django_api.queue_json_publish") as m:
m.side_effect = AssertionError( m.side_effect = AssertionError(
"Events should be sent only after the transaction commits." "Events should be sent only after the transaction commits."
) )

View File

@@ -1060,7 +1060,7 @@ class ReactionAPIEventTest(EmojiReactionBase):
"reaction_type": "unicode_emoji", "reaction_type": "unicode_emoji",
} }
with self.capture_send_event_calls(expected_num_events=1) as events: with self.capture_send_event_calls(expected_num_events=1) as events:
with mock.patch("zerver.actions.reactions.send_event") as m: with mock.patch("zerver.tornado.django_api.queue_json_publish") as m:
m.side_effect = AssertionError( m.side_effect = AssertionError(
"Events should be sent only after the transaction commits!" "Events should be sent only after the transaction commits!"
) )
@@ -1143,7 +1143,7 @@ class ReactionAPIEventTest(EmojiReactionBase):
) )
with self.capture_send_event_calls(expected_num_events=1): with self.capture_send_event_calls(expected_num_events=1):
with mock.patch("zerver.actions.reactions.send_event") as m: with mock.patch("zerver.tornado.django_api.queue_json_publish") as m:
m.side_effect = AssertionError( m.side_effect = AssertionError(
"Events should be sent only after the transaction commits." "Events should be sent only after the transaction commits."
) )

View File

@@ -195,7 +195,7 @@ class TestBasics(ZulipTestCase):
message_id = self.send_stream_message(hamlet, "Denmark") message_id = self.send_stream_message(hamlet, "Denmark")
with self.capture_send_event_calls(expected_num_events=1): with self.capture_send_event_calls(expected_num_events=1):
with mock.patch("zerver.actions.submessage.send_event") as m: with mock.patch("zerver.tornado.django_api.queue_json_publish") as m:
m.side_effect = AssertionError( m.side_effect = AssertionError(
"Events should be sent only after the transaction commits." "Events should be sent only after the transaction commits."
) )

View File

@@ -6,6 +6,7 @@ from urllib.parse import urlparse
import orjson import orjson
import requests import requests
from django.conf import settings from django.conf import settings
from django.db import transaction
from requests.adapters import ConnectionError, HTTPAdapter from requests.adapters import ConnectionError, HTTPAdapter
from requests.models import PreparedRequest, Response from requests.models import PreparedRequest, Response
from urllib3.util import Retry from urllib3.util import Retry
@@ -186,3 +187,9 @@ def send_event(
dict(event=event, users=port_users), dict(event=event, users=port_users),
lambda *args, **kwargs: send_notification_http(port, *args, **kwargs), lambda *args, **kwargs: send_notification_http(port, *args, **kwargs),
) )
def send_event_on_commit(
realm: Realm, event: Mapping[str, Any], users: Union[Iterable[int], Iterable[Mapping[str, Any]]]
) -> None:
transaction.on_commit(lambda: send_event(realm, event, users))