mirror of
https://github.com/zulip/zulip.git
synced 2025-11-01 12:33:40 +00:00
Fix missing aggregated info in real-time sync race for presence.
- Add aggregated info to real-time updated presence status. - Update `presence events` test case with adding aggregated information to presence event. - Add test case for updating presence status for user which send state from multiple clients. Fixes #4282.
This commit is contained in:
@@ -2344,7 +2344,7 @@ def send_presence_changed(user_profile, presence):
|
||||
presence_dict = presence.to_dict()
|
||||
event = dict(type="presence", email=user_profile.email,
|
||||
server_timestamp=time.time(),
|
||||
presence={presence_dict['client']: presence.to_dict()})
|
||||
presence={presence_dict['client']: presence_dict})
|
||||
send_event(event, active_user_ids(user_profile.realm))
|
||||
|
||||
def consolidate_client(client):
|
||||
|
||||
@@ -29,7 +29,7 @@ from zerver.lib.actions import validate_user_access_to_subscribers_helper, \
|
||||
gather_subscriptions_helper, get_realm_domains, \
|
||||
get_status_dict, streams_to_dicts_sorted
|
||||
from zerver.tornado.event_queue import request_event_queue, get_user_events
|
||||
from zerver.models import Client, Message, Realm, UserProfile, \
|
||||
from zerver.models import Client, Message, Realm, UserPresence, UserProfile, \
|
||||
get_user_profile_by_email, get_user_profile_by_id, \
|
||||
get_active_user_dicts_in_realm, realm_filters_for_realm, \
|
||||
get_owned_bot_dicts, custom_profile_fields_for_realm
|
||||
@@ -349,7 +349,9 @@ def apply_event(state, event, user_profile, include_subscribers):
|
||||
user_id in sub['subscribers']):
|
||||
sub['subscribers'].remove(user_id)
|
||||
elif event['type'] == "presence":
|
||||
state['presences'][event['email']] = event['presence']
|
||||
# TODO: Add user_id to presence update events / state format!
|
||||
presence_user_profile = get_user_profile_by_email(event['email'])
|
||||
state['presences'][event['email']] = UserPresence.get_status_dict_by_user(presence_user_profile)[event['email']]
|
||||
elif event['type'] == "update_message":
|
||||
# The client will get the updated message directly
|
||||
pass
|
||||
|
||||
@@ -1567,9 +1567,9 @@ class UserPresence(models.Model):
|
||||
return user_statuses
|
||||
|
||||
@staticmethod
|
||||
def to_presence_dict(client_name, status, dt, push_enabled=None,
|
||||
has_push_devices=None, is_mirror_dummy=None):
|
||||
# type: (Text, int, datetime.datetime, Optional[bool], Optional[bool], Optional[bool]) -> Dict[str, Any]
|
||||
def to_presence_dict(client_name, status, dt, push_enabled=False,
|
||||
has_push_devices=False, is_mirror_dummy=None):
|
||||
# type: (Text, int, datetime.datetime, bool, bool, Optional[bool]) -> Dict[str, Any]
|
||||
presence_val = UserPresence.status_to_string(status)
|
||||
|
||||
timestamp = datetime_to_timestamp(dt)
|
||||
|
||||
@@ -603,23 +603,47 @@ class EventsRegisterTest(ZulipTestCase):
|
||||
def test_presence_events(self):
|
||||
# type: () -> None
|
||||
schema_checker = self.check_events_dict([
|
||||
('type', equals('pointer')),
|
||||
('type', equals('presence')),
|
||||
('email', check_string),
|
||||
('timestamp', check_float),
|
||||
('server_timestamp', check_float),
|
||||
('presence', check_dict_only([
|
||||
# TODO: Add more here once the test below works
|
||||
('website', check_dict_only([
|
||||
('status', equals('active')),
|
||||
('timestamp', check_int),
|
||||
('client', check_string),
|
||||
('pushable', check_bool),
|
||||
])),
|
||||
])),
|
||||
])
|
||||
# BUG: Marked as failing for now because this is a failing
|
||||
# test, due to the `aggregated` feature not being supported by
|
||||
# our events code.
|
||||
events = self.do_test(lambda: do_update_user_presence(
|
||||
self.user_profile, get_client("website"), timezone_now(), UserPresence.ACTIVE))
|
||||
error = schema_checker('events[0]', events[0])
|
||||
self.assert_on_error(error)
|
||||
|
||||
with self.assertRaises(AssertionError):
|
||||
events = self.do_test(lambda: do_update_user_presence(
|
||||
self.user_profile, get_client("website"), timezone_now(), UserPresence.ACTIVE))
|
||||
# Marked as nocoverage since unreachable
|
||||
error = schema_checker('events[0]', events[0]) # nocoverage
|
||||
self.assert_on_error(error) # nocoverage
|
||||
def test_presence_events_multiple_clients(self):
|
||||
# type: () -> None
|
||||
schema_checker_android = self.check_events_dict([
|
||||
('type', equals('presence')),
|
||||
('email', check_string),
|
||||
('server_timestamp', check_float),
|
||||
('presence', check_dict_only([
|
||||
('ZulipAndroid/1.0', check_dict_only([
|
||||
('status', equals('idle')),
|
||||
('timestamp', check_int),
|
||||
('client', check_string),
|
||||
('pushable', check_bool),
|
||||
])),
|
||||
])),
|
||||
])
|
||||
self.client_post("/api/v1/users/me/presence", {'status': 'idle'},
|
||||
HTTP_USER_AGENT="ZulipAndroid/1.0",
|
||||
**self.api_auth(self.user_profile.email))
|
||||
self.do_test(lambda: do_update_user_presence(
|
||||
self.user_profile, get_client("website"), timezone_now(), UserPresence.ACTIVE))
|
||||
events = self.do_test(lambda: do_update_user_presence(
|
||||
self.user_profile, get_client("ZulipAndroid/1.0"), timezone_now(), UserPresence.IDLE))
|
||||
error = schema_checker_android('events[0]', events[0])
|
||||
self.assert_on_error(error)
|
||||
|
||||
def test_pointer_events(self):
|
||||
# type: () -> None
|
||||
|
||||
Reference in New Issue
Block a user