event_queue: Fix missing copy for edit-message events.

Apparently, our edit-message events did not guarantee that the outer
wrapper dictionary, which is intended to be unique for each client,
was unique for every client (instead only ensuring it was unique for
each user).

This led to clients unexpectedly getting last_event_id validation
errors in this code path when a user had multiple connected clients,
because the linear ordering of event IDs within a given queue was
corrupted.
This commit is contained in:
Tim Abbott 2019-08-06 13:34:52 -07:00
parent 8c26183c65
commit fd2a63b049
1 changed files with 11 additions and 1 deletions

View File

@ -152,6 +152,11 @@ class ClientDescriptor:
self._timeout_handle = None
def add_event(self, event: Dict[str, Any]) -> None:
# Any dictionary passed into this function must be a unique
# dictionary (potentially a shallow copy of a shared data
# structure), since the event_queue data structures will
# mutate it to add the queue-specific unique `id` of that
# event to the outer event dictionary.
if self.current_handler_id is not None:
handler = get_handler_by_id(self.current_handler_id)
async_request_timer_restart(handler._request)
@ -889,6 +894,9 @@ def process_message_event(event_template: Mapping[str, Any], users: Iterable[Map
if ('mirror' in sending_client and
sending_client.lower() == client.client_type_name.lower()):
continue
# We don't need to create a new dict here, since the
# `user_event` was already constructed from scratch above.
client.add_event(user_event)
def process_event(event: Mapping[str, Any], users: Iterable[int]) -> None:
@ -907,7 +915,9 @@ def process_userdata_event(event_template: Mapping[str, Any], users: Iterable[Ma
for client in get_client_descriptors_for_user(user_profile_id):
if client.accepts_event(user_event):
client.add_event(user_event)
# We need to do another shallow copy, or we risk
# sending the same event to multiple clients.
client.add_event(dict(user_event))
def process_message_update_event(event_template: Mapping[str, Any],
users: Iterable[Mapping[str, Any]]) -> None: