Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

recent_view: Refactor conversation data to prevent fetching messages. #30137

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

evykassirer
Copy link
Collaborator

The motivation is that when we're able to provide a dedicated efficient API for the recent view, it's probably not going to preserve the invariant that any topic in this view has a message in message_store.

Further discussion here

web/src/hash_util.ts Outdated Show resolved Hide resolved
const sample_messages = [];
sample_messages[0] = {
stream_id: stream1,
id: (id += 1),
id: 1,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed these to numbers so it would be easier to find the messages by their ids when setting up tests, but I can change it back if that's preferred.


if (msg.type === "private") {
// Display recipient contains user information for DMs.
assert(typeof msg.display_recipient !== "string");
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just preserving old logic, but ideally we'd refactor the message type so that we don't have to make this assertion.

Copy link
Member

@amanagr amanagr May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we need to also think about how we are going to update the properties here which can change.

Like we used to update unread_count by simply calling inplace_rerender since that would get the latest unread count from last_msg_id and update it, but that won't work anymore since we are using a cached value.

We need to hook server_events for this. We could use the process_message as an opportunity to update them but that won't be reliabl, so probably a good idea to skip updating them here.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with @amanagr that we're going to need to be very careful to make sure things that could change any of the data that you're caching here, which is quite a lot (name changes go into display_recipient, etc.).

Realistically that means this is the wrong design; we should be only caching the metadata that we think is stable, not computed properties like display_recipient, which can just as well be processed later.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to lay out a bit more how I'm thinking this should work: A server API endpoint that sent data on what recent conversations exist would not include the following:

  • unread data -- clients should combine its unread data set with the recent view data to display a complete view.
  • Metadata on users, like names/etc. that go into display recipients -- I'd expect it to just have stream/user IDs.

Instead, I'd expect it to just have (1) list of participated user IDs, (2) last_message_id, (3) last_message_timestamp, (4) type and location of the message.

So I think it's correct for the data structure we're defining here to have those properties as well, and rely on combining that reasonably normalized data set with the unread data set and people/stream_data data sets, just like it will with which topics are followed in order to display that detail.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed to this branch with an extra commit to try addressing this -- let me know what you think! I wasn't totally sure which data we can rely on to be stable.

participated: boolean;
type: "private" | "stream";
};
type Row = ConversationData;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to define this type if they are the same?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be an additional commit to clean that up if that's convenient.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure here -- they were separate types before despite being the same. Was there a reason for that? I thought maybe there was a semantic reason for it or something. Would you prefer they both be called ConversationData?

@evykassirer
Copy link
Collaborator Author

FYI @timabbott Aman said on CZO:

You should wait for a review from Tim Abbott before making any changes here though.

stream_id: number;
topic: string;
},
): string {
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this instead just take a ConversationData? Not sure why you're defining this other abbreviated type here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because we call it in process_message with a message:

const key = get_key_from_conversation_data(msg);

and ConversationData has attributes that aren't on Message which also aren't needed here, but these attributes I listed are on both types and are the only attributes we need here.

@@ -19,7 +19,7 @@ export type DisplayRecipientUser = {
email: string;
full_name: string;
id: number;
is_mirror_dummy: boolean;
is_mirror_dummy?: boolean;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like this is used at all in the frontend, so maybe we want to remove it completely here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, looks like we can avoid sending it to the client to reduce response data. @timabbott FYI

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evykassirer I think you should start a czo discussion to fast track that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// See `echo.build_display_recipient` for more on this.
return {
// TODO(evy): What to do here for typing purposes? Or can we assume all users are defined here?
// I don't know much aobut zephyr and when it's relevant.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question here!

Copy link
Member

@amanagr amanagr Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For recent view, I think it makes sense to treat them as normal users unless we have problems generating their avatar and display user profile popover. I don't have much context here either.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll let @timabbott comment before removing it then

}

// This mirrors the structure of `echo.build_display_recipient`, using data
// found in `ConversationData`.
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It felt like it would be pretty hard to generalize echo.build_display_recipient to work for this case too, so I just built a variation on it for here.

@evykassirer
Copy link
Collaborator Author

@timabbott this is ready for your review again. I've responded to the open comments, some I wanted to check in with you about what to do or if what I did seems right. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants