mirror of
https://github.com/zulip/zulip.git
synced 2025-11-06 23:13:25 +00:00
refactor: Extract peer_data.js.
This de-clutters stream_data a bit. Since our peer data is our biggest performance concern, I want to contain any optimizations to a fairly well-focused module. The name `peer_data` is a bit of a compromise, since we already have `subs.js` and we use `sub` as a variable name for stream records throughout our code, but it's consistent with our event nomenclature (peer/add, peer/remove) and it's short while still being fairly easy to find with grep.
This commit is contained in:
145
static/js/peer_data.js
Normal file
145
static/js/peer_data.js
Normal file
@@ -0,0 +1,145 @@
|
||||
const {LazySet} = require("./lazy_set");
|
||||
const people = require("./people");
|
||||
|
||||
/*
|
||||
|
||||
For legacy reasons this module is mostly tested
|
||||
by frontend_tests/node_tests/stream_data.js.
|
||||
|
||||
*/
|
||||
|
||||
// This maps a stream_id to a LazySet of user_ids who are subscribed.
|
||||
// We maintain the invariant that this has keys for all all stream_ids
|
||||
// that we track in the other data structures. We intialize it during
|
||||
// clear_subscriptions.
|
||||
let stream_subscribers;
|
||||
|
||||
export function clear() {
|
||||
stream_subscribers = new Map();
|
||||
}
|
||||
|
||||
export function maybe_clear_subscribers(sub) {
|
||||
if (!stream_subscribers.has(sub.stream_id)) {
|
||||
set_subscribers(sub, []);
|
||||
}
|
||||
}
|
||||
|
||||
export function is_subscriber_subset(sub1, sub2) {
|
||||
const stream_id1 = sub1.stream_id;
|
||||
const stream_id2 = sub2.stream_id;
|
||||
|
||||
const sub1_set = stream_subscribers.get(stream_id1);
|
||||
const sub2_set = stream_subscribers.get(stream_id2);
|
||||
|
||||
if (sub1_set && sub2_set) {
|
||||
return Array.from(sub1_set.keys()).every((key) => sub2_set.has(key));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function potential_subscribers(stream_id) {
|
||||
/*
|
||||
This is a list of unsubscribed users
|
||||
for the current stream, who the current
|
||||
user could potentially subscribe to the
|
||||
stream. This may include some bots.
|
||||
|
||||
We currently use it for typeahead in
|
||||
stream_edit.js.
|
||||
|
||||
This may be a superset of the actual
|
||||
subscribers that you can change in some cases
|
||||
(like if you're a guest?); we should refine this
|
||||
going forward, especially if we use it for something
|
||||
other than typeahead. (The guest use case
|
||||
may be moot now for other reasons.)
|
||||
*/
|
||||
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
|
||||
function is_potential_subscriber(person) {
|
||||
// Use verbose style to force better test
|
||||
// coverage, plus we may add more conditions over
|
||||
// time.
|
||||
if (subscribers.has(person.user_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return people.filter_all_users(is_potential_subscriber);
|
||||
}
|
||||
|
||||
export function get_subscriber_count(stream_id) {
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
|
||||
if (!subscribers) {
|
||||
blueslip.warn("We got a get_subscriber_count call for an untracked stream: " + stream_id);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return subscribers.size;
|
||||
}
|
||||
|
||||
export function get_subscribers(stream_id) {
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
|
||||
if (typeof subscribers === "undefined") {
|
||||
blueslip.warn("We called get_subscribers for an untracked stream: " + stream_id);
|
||||
return [];
|
||||
}
|
||||
|
||||
return Array.from(subscribers.keys());
|
||||
}
|
||||
|
||||
export function set_subscribers(sub, user_ids) {
|
||||
const subscribers = new LazySet(user_ids || []);
|
||||
stream_subscribers.set(sub.stream_id, subscribers);
|
||||
}
|
||||
|
||||
export function add_subscriber(stream_id, user_id) {
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
if (typeof subscribers === "undefined") {
|
||||
blueslip.warn("We got an add_subscriber call for an untracked stream: " + stream_id);
|
||||
return false;
|
||||
}
|
||||
const person = people.get_by_user_id(user_id);
|
||||
if (person === undefined) {
|
||||
blueslip.error("We tried to add invalid subscriber: " + user_id);
|
||||
return false;
|
||||
}
|
||||
subscribers.add(user_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function remove_subscriber(stream_id, user_id) {
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
if (typeof subscribers === "undefined") {
|
||||
blueslip.warn("We got a remove_subscriber call for an untracked stream " + stream_id);
|
||||
return false;
|
||||
}
|
||||
if (!subscribers.has(user_id)) {
|
||||
blueslip.warn("We tried to remove invalid subscriber: " + user_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
subscribers.delete(user_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function is_user_subscribed(stream_id, user_id) {
|
||||
// Most callers should call stream_data.is_user_subscribed,
|
||||
// which does additional checks.
|
||||
|
||||
const subscribers = stream_subscribers.get(stream_id);
|
||||
if (typeof subscribers === "undefined") {
|
||||
blueslip.warn("We called is_user_subscribed for an untracked stream: " + stream_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return subscribers.has(user_id);
|
||||
}
|
||||
Reference in New Issue
Block a user