mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 16:37:23 +00:00
stream_topic_history: Track the most recent message in streams.
This adds a way to keep track of max_message_id of a stream and fetch it using the method get_max_message_id(). This will be useful for sorting streams by most recent activity which will be implemented in the upcoming commit. Essentially rewritten by tabbott to have a coherent tracking system, and provide documentation. Part of #10794.
This commit is contained in:
committed by
Tim Abbott
parent
5598f8f6b0
commit
735785f985
@@ -16,7 +16,9 @@ run_test('basics', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let history = stream_topic_history.get_recent_topic_names(stream_id);
|
let history = stream_topic_history.get_recent_topic_names(stream_id);
|
||||||
|
let max_message_id = stream_topic_history.get_max_message_id(stream_id);
|
||||||
assert.deepEqual(history, ['toPic1']);
|
assert.deepEqual(history, ['toPic1']);
|
||||||
|
assert.deepEqual(max_message_id, 101);
|
||||||
|
|
||||||
stream_topic_history.add_message({
|
stream_topic_history.add_message({
|
||||||
stream_id: stream_id,
|
stream_id: stream_id,
|
||||||
@@ -24,7 +26,9 @@ run_test('basics', () => {
|
|||||||
topic_name: 'Topic1',
|
topic_name: 'Topic1',
|
||||||
});
|
});
|
||||||
history = stream_topic_history.get_recent_topic_names(stream_id);
|
history = stream_topic_history.get_recent_topic_names(stream_id);
|
||||||
|
max_message_id = stream_topic_history.get_max_message_id(stream_id);
|
||||||
assert.deepEqual(history, ['Topic1']);
|
assert.deepEqual(history, ['Topic1']);
|
||||||
|
assert.deepEqual(max_message_id, 102);
|
||||||
|
|
||||||
stream_topic_history.add_message({
|
stream_topic_history.add_message({
|
||||||
stream_id: stream_id,
|
stream_id: stream_id,
|
||||||
@@ -32,7 +36,9 @@ run_test('basics', () => {
|
|||||||
topic_name: 'topic2',
|
topic_name: 'topic2',
|
||||||
});
|
});
|
||||||
history = stream_topic_history.get_recent_topic_names(stream_id);
|
history = stream_topic_history.get_recent_topic_names(stream_id);
|
||||||
|
max_message_id = stream_topic_history.get_max_message_id(stream_id);
|
||||||
assert.deepEqual(history, ['topic2', 'Topic1']);
|
assert.deepEqual(history, ['topic2', 'Topic1']);
|
||||||
|
assert.deepEqual(max_message_id, 103);
|
||||||
|
|
||||||
// Removing first topic1 message has no effect.
|
// Removing first topic1 message has no effect.
|
||||||
stream_topic_history.remove_message({
|
stream_topic_history.remove_message({
|
||||||
@@ -41,6 +47,9 @@ run_test('basics', () => {
|
|||||||
});
|
});
|
||||||
history = stream_topic_history.get_recent_topic_names(stream_id);
|
history = stream_topic_history.get_recent_topic_names(stream_id);
|
||||||
assert.deepEqual(history, ['topic2', 'Topic1']);
|
assert.deepEqual(history, ['topic2', 'Topic1']);
|
||||||
|
// Removing a topic message shouldn't effect the max_message_id.
|
||||||
|
max_message_id = stream_topic_history.get_max_message_id(stream_id);
|
||||||
|
assert.deepEqual(max_message_id, 103);
|
||||||
|
|
||||||
// Removing second topic1 message removes the topic.
|
// Removing second topic1 message removes the topic.
|
||||||
stream_topic_history.remove_message({
|
stream_topic_history.remove_message({
|
||||||
|
|||||||
@@ -44,26 +44,55 @@ exports.stream_has_topics = function (stream_id) {
|
|||||||
|
|
||||||
exports.per_stream_history = function (stream_id) {
|
exports.per_stream_history = function (stream_id) {
|
||||||
/*
|
/*
|
||||||
Each stream has a dictionary of topics.
|
For a given stream, this structure has a dictionary of topics.
|
||||||
The main getter of this object is
|
The main getter of this object is get_recent_topic_names, and
|
||||||
get_recent_topic_names, and we just
|
we just sort on the fly every time we are called.
|
||||||
sort on the fly every time we are
|
|
||||||
called.
|
Attributes for a topic are:
|
||||||
|
* message_id: The latest message_id in the topic. Only usable
|
||||||
|
for imprecise applications like sorting. The message_id
|
||||||
|
cannot be fully accurate given message editing and deleting
|
||||||
|
(as we don't have a way to handle the latest message in a
|
||||||
|
stream having its stream edited or deleted).
|
||||||
|
|
||||||
|
TODO: We can probably fix this limitation by doing a
|
||||||
|
single-message `GET /messages` query with anchor="latest",
|
||||||
|
num_before=0, num_after=0, to update this field when its
|
||||||
|
value becomes ambiguous. Or probably better to avoid a
|
||||||
|
thundering herd (of a fast query), having the server send
|
||||||
|
the data needed to do this update in stream/topic-edit and
|
||||||
|
delete events (just the new max_message_id for the relevant
|
||||||
|
topic would likely suffice, though we need to think about
|
||||||
|
private stream corner cases).
|
||||||
|
* pretty_name: The topic_name, with original case.
|
||||||
|
* historical: Whether the user actually received any messages in
|
||||||
|
the topic (has UserMessage rows) or is just viewing the stream.
|
||||||
|
* count: Number of known messages in the topic. Used to detect
|
||||||
|
when the last messages in a topic were moved to other topics or
|
||||||
|
deleted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const topics = new FoldDict();
|
const topics = new FoldDict();
|
||||||
|
// Most recent message ID for the stream.
|
||||||
|
let max_message_id = 0;
|
||||||
const self = {};
|
const self = {};
|
||||||
|
|
||||||
self.has_topics = function () {
|
self.has_topics = function () {
|
||||||
return topics.size !== 0;
|
return topics.size !== 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.update_stream_max_message_id = function (message_id) {
|
||||||
|
if (message_id > max_message_id) {
|
||||||
|
max_message_id = message_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.add_or_update = function (opts) {
|
self.add_or_update = function (opts) {
|
||||||
const topic_name = opts.topic_name;
|
const topic_name = opts.topic_name;
|
||||||
let message_id = opts.message_id || 0;
|
let message_id = opts.message_id || 0;
|
||||||
|
|
||||||
message_id = parseInt(message_id, 10);
|
message_id = parseInt(message_id, 10);
|
||||||
|
self.update_stream_max_message_id(message_id);
|
||||||
|
|
||||||
const existing = topics.get(topic_name);
|
const existing = topics.get(topic_name);
|
||||||
|
|
||||||
@@ -137,6 +166,7 @@ exports.per_stream_history = function (stream_id) {
|
|||||||
pretty_name: topic_name,
|
pretty_name: topic_name,
|
||||||
historical: true,
|
historical: true,
|
||||||
});
|
});
|
||||||
|
self.update_stream_max_message_id(message_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -159,6 +189,10 @@ exports.per_stream_history = function (stream_id) {
|
|||||||
return names;
|
return names;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.get_max_message_id = function () {
|
||||||
|
return max_message_id;
|
||||||
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -233,6 +267,12 @@ exports.get_recent_topic_names = function (stream_id) {
|
|||||||
return history.get_recent_topic_names();
|
return history.get_recent_topic_names();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.get_max_message_id = function (stream_id) {
|
||||||
|
const history = exports.find_or_create(stream_id);
|
||||||
|
|
||||||
|
return history.get_max_message_id();
|
||||||
|
};
|
||||||
|
|
||||||
exports.reset = function () {
|
exports.reset = function () {
|
||||||
// This is only used by tests.
|
// This is only used by tests.
|
||||||
stream_dict.clear();
|
stream_dict.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user