mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 16:37:23 +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()
|
presence_dict = presence.to_dict()
|
||||||
event = dict(type="presence", email=user_profile.email,
|
event = dict(type="presence", email=user_profile.email,
|
||||||
server_timestamp=time.time(),
|
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))
|
send_event(event, active_user_ids(user_profile.realm))
|
||||||
|
|
||||||
def consolidate_client(client):
|
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, \
|
gather_subscriptions_helper, get_realm_domains, \
|
||||||
get_status_dict, streams_to_dicts_sorted
|
get_status_dict, streams_to_dicts_sorted
|
||||||
from zerver.tornado.event_queue import request_event_queue, get_user_events
|
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_user_profile_by_email, get_user_profile_by_id, \
|
||||||
get_active_user_dicts_in_realm, realm_filters_for_realm, \
|
get_active_user_dicts_in_realm, realm_filters_for_realm, \
|
||||||
get_owned_bot_dicts, custom_profile_fields_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']):
|
user_id in sub['subscribers']):
|
||||||
sub['subscribers'].remove(user_id)
|
sub['subscribers'].remove(user_id)
|
||||||
elif event['type'] == "presence":
|
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":
|
elif event['type'] == "update_message":
|
||||||
# The client will get the updated message directly
|
# The client will get the updated message directly
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1567,9 +1567,9 @@ class UserPresence(models.Model):
|
|||||||
return user_statuses
|
return user_statuses
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_presence_dict(client_name, status, dt, push_enabled=None,
|
def to_presence_dict(client_name, status, dt, push_enabled=False,
|
||||||
has_push_devices=None, is_mirror_dummy=None):
|
has_push_devices=False, is_mirror_dummy=None):
|
||||||
# type: (Text, int, datetime.datetime, Optional[bool], Optional[bool], Optional[bool]) -> Dict[str, Any]
|
# type: (Text, int, datetime.datetime, bool, bool, Optional[bool]) -> Dict[str, Any]
|
||||||
presence_val = UserPresence.status_to_string(status)
|
presence_val = UserPresence.status_to_string(status)
|
||||||
|
|
||||||
timestamp = datetime_to_timestamp(dt)
|
timestamp = datetime_to_timestamp(dt)
|
||||||
|
|||||||
@@ -603,23 +603,47 @@ class EventsRegisterTest(ZulipTestCase):
|
|||||||
def test_presence_events(self):
|
def test_presence_events(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
schema_checker = self.check_events_dict([
|
schema_checker = self.check_events_dict([
|
||||||
('type', equals('pointer')),
|
('type', equals('presence')),
|
||||||
('email', check_string),
|
('email', check_string),
|
||||||
('timestamp', check_float),
|
('server_timestamp', check_float),
|
||||||
('presence', check_dict_only([
|
('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.
|
|
||||||
|
|
||||||
with self.assertRaises(AssertionError):
|
|
||||||
events = self.do_test(lambda: do_update_user_presence(
|
events = self.do_test(lambda: do_update_user_presence(
|
||||||
self.user_profile, get_client("website"), timezone_now(), UserPresence.ACTIVE))
|
self.user_profile, get_client("website"), timezone_now(), UserPresence.ACTIVE))
|
||||||
# Marked as nocoverage since unreachable
|
error = schema_checker('events[0]', events[0])
|
||||||
error = schema_checker('events[0]', events[0]) # nocoverage
|
self.assert_on_error(error)
|
||||||
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):
|
def test_pointer_events(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
|||||||
Reference in New Issue
Block a user