mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 13:33:24 +00:00
presence: Prep for upcoming changes to server data.
In the next commit we're going to change what the
server sends for the following:
- page_params
- server responses to /json/users/me/presence
We will **not** yet be changing the format of the data
that we get in events when users update their presence.
It's also just a bit in flux what our final formats
will be for various presence payloads, and different
optimizations may lead us to use different data
structures in different payloads.
So for now we decouple these two things:
raw_info: this is intended to represent a
snapshot of the latest data from the
server, including some data like
timestamps that are only used
in downstream calculations and not
user-facing
exports.presence_info: this is calculated
info for modules like buddy_data that
just need to know active vs. idle and
last_active_date
Another change that happens here is we rename
set_info_for_user to update_info_for_event,
which just makes it clear that the function
expects data in the "event" format (as opposed
to the format for page_params or server
responses).
As of now keeping the intermediate raw_info data
around feels slightly awkward, because we just
immediately calculate presence_info for any kind
of update. This may be sorta surprising if you
just skim the code and see the various timeout
constants. You would think we might be automatically
expiring "active" statuses in the client due to
the simple passage of time, but in fact the precise
places we do this are all triggered by new data
from the server and we re-calculate statuses
immediately.
(There are indirect ways that clients
have timing logic, since they ask the
server for new data at various intervals, but a
smarter client could simply expire users on its
own, or at least with a more efficient transfer
of info between it and the server. One of
the thing that complicates client-side logic
is that server and client clocks may be out
of sync. Also, it's not inherently super expensive
to get updates from the server.)
This commit is contained in:
@@ -240,8 +240,8 @@ run_test('level', () => {
|
|||||||
timestamp: server_time,
|
timestamp: server_time,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
presence.set_info_for_user(me.user_id, info, server_time);
|
presence.update_info_from_event(me.user_id, info, server_time);
|
||||||
presence.set_info_for_user(selma.user_id, info, server_time);
|
presence.update_info_from_event(selma.user_id, info, server_time);
|
||||||
|
|
||||||
assert.equal(buddy_data.level(me.user_id), 0);
|
assert.equal(buddy_data.level(me.user_id), 0);
|
||||||
assert.equal(buddy_data.level(selma.user_id), 1);
|
assert.equal(buddy_data.level(selma.user_id), 1);
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ run_test('last_active_date', () => {
|
|||||||
assert.deepEqual(presence.last_active_date(alice.user_id), {seconds: 500000});
|
assert.deepEqual(presence.last_active_date(alice.user_id), {seconds: 500000});
|
||||||
});
|
});
|
||||||
|
|
||||||
run_test('set_info_for_user', () => {
|
run_test('update_info_from_event', () => {
|
||||||
const server_time = 500;
|
const server_time = 500;
|
||||||
const info = {
|
const info = {
|
||||||
website: {
|
website: {
|
||||||
@@ -214,7 +214,7 @@ run_test('set_info_for_user', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
presence.presence_info.delete(alice.user_id);
|
presence.presence_info.delete(alice.user_id);
|
||||||
presence.set_info_for_user(alice.user_id, info, server_time);
|
presence.update_info_from_event(alice.user_id, info, server_time);
|
||||||
|
|
||||||
const expected = { status: 'active', last_active: 500 };
|
const expected = { status: 'active', last_active: 500 };
|
||||||
assert.deepEqual(presence.presence_info.get(alice.user_id), expected);
|
assert.deepEqual(presence.presence_info.get(alice.user_id), expected);
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ exports.initialize = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.update_presence_info = function (user_id, info, server_time) {
|
exports.update_presence_info = function (user_id, info, server_time) {
|
||||||
presence.set_info_for_user(user_id, info, server_time);
|
presence.update_info_from_event(user_id, info, server_time);
|
||||||
exports.redraw_user(user_id);
|
exports.redraw_user(user_id);
|
||||||
exports.update_huddles();
|
exports.update_huddles();
|
||||||
pm_list.update_private_messages();
|
pm_list.update_private_messages();
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
// This module just manages data. See activity.js for
|
// This module just manages data. See activity.js for
|
||||||
// the UI of our buddy list.
|
// the UI of our buddy list.
|
||||||
|
|
||||||
// Dictionary mapping user_id -> presence data. May contain user_id
|
// The following Maps have user_id as the key. Some of the
|
||||||
// values that are not yet registered in people.js (see long comment
|
// user_ids may not yet be registered in people.js.
|
||||||
// in `set_info` below for details).
|
// See the long comment in `set_info` below for details.
|
||||||
exports.presence_info = new Map();
|
|
||||||
|
|
||||||
|
// In future commits we'll use raw_info to facilitate
|
||||||
|
// handling server events and/or timeout events.
|
||||||
|
const raw_info = new Map();
|
||||||
|
exports.presence_info = new Map();
|
||||||
|
|
||||||
/* Mark users as offline after 140 seconds since their last checkin,
|
/* Mark users as offline after 140 seconds since their last checkin,
|
||||||
* Keep in sync with zerver/tornado/event_queue.py:receiver_is_idle
|
* Keep in sync with zerver/tornado/event_queue.py:receiver_is_idle
|
||||||
@@ -17,7 +20,7 @@ const BIG_REALM_COUNT = 250;
|
|||||||
exports.is_active = function (user_id) {
|
exports.is_active = function (user_id) {
|
||||||
if (exports.presence_info.has(user_id)) {
|
if (exports.presence_info.has(user_id)) {
|
||||||
const status = exports.presence_info.get(user_id).status;
|
const status = exports.presence_info.get(user_id).status;
|
||||||
if (status && status === "active") {
|
if (status === "active") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,14 +77,22 @@ function status_from_timestamp(baseline_time, info) {
|
|||||||
// For testing
|
// For testing
|
||||||
exports._status_from_timestamp = status_from_timestamp;
|
exports._status_from_timestamp = status_from_timestamp;
|
||||||
|
|
||||||
exports.set_info_for_user = function (user_id, info, server_time) {
|
exports.update_info_from_event = function (user_id, info, server_time) {
|
||||||
|
raw_info.set(user_id, {
|
||||||
|
info: info,
|
||||||
|
server_time: server_time,
|
||||||
|
});
|
||||||
|
|
||||||
const status = status_from_timestamp(server_time, info);
|
const status = status_from_timestamp(server_time, info);
|
||||||
exports.presence_info.set(user_id, status);
|
exports.presence_info.set(user_id, status);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.set_info = function (presences, server_timestamp) {
|
exports.set_info = function (presences, server_timestamp) {
|
||||||
|
raw_info.clear();
|
||||||
exports.presence_info.clear();
|
exports.presence_info.clear();
|
||||||
for (const [user_id_str, info] of Object.entries(presences)) {
|
for (const [user_id_str, info] of Object.entries(presences)) {
|
||||||
|
const user_id = parseInt(user_id_str, 10);
|
||||||
|
|
||||||
// Note: In contrast with essentially every other piece of
|
// Note: In contrast with essentially every other piece of
|
||||||
// state updates we receive from the server, precense updates
|
// state updates we receive from the server, precense updates
|
||||||
// are pulled independently from server_events_dispatch.js.
|
// are pulled independently from server_events_dispatch.js.
|
||||||
@@ -89,15 +100,18 @@ exports.set_info = function (presences, server_timestamp) {
|
|||||||
// This means that if we're coming back from offline and new
|
// This means that if we're coming back from offline and new
|
||||||
// users were created in the meantime, we'll be populating
|
// users were created in the meantime, we'll be populating
|
||||||
// exports.presence_info with user IDs not yet present in
|
// exports.presence_info with user IDs not yet present in
|
||||||
// people.js. This is safe because we always access
|
// people.js. This is safe because we when we build the
|
||||||
// exports.presence_info as a filter on sets of users obtained
|
// buddy list, we only process user_ids that are in people.js
|
||||||
// elsewhere, but we need to be careful to avoid trying to
|
// (because we need their name, etc.).
|
||||||
// look up user_ids obtained via presence_info in other data
|
|
||||||
// sources.
|
raw_info.set(user_id, {
|
||||||
|
info: info,
|
||||||
|
server_time: server_timestamp,
|
||||||
|
});
|
||||||
|
|
||||||
const status = status_from_timestamp(server_timestamp,
|
const status = status_from_timestamp(server_timestamp,
|
||||||
info);
|
info);
|
||||||
|
|
||||||
const user_id = parseInt(user_id_str, 10);
|
|
||||||
exports.presence_info.set(user_id, status);
|
exports.presence_info.set(user_id, status);
|
||||||
}
|
}
|
||||||
exports.update_info_for_small_realm();
|
exports.update_info_for_small_realm();
|
||||||
|
|||||||
Reference in New Issue
Block a user