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

feat: add cursor pagination on chat.syncMessages #33273

Closed

Conversation

ricardogarim
Copy link
Contributor

@ricardogarim ricardogarim commented Sep 12, 2024

As per CORE-686, this PR introduces cursor pagination to the messages/get Meteor method route, which supports the chat.syncMessages route. This improvement allows users to retrieve updates from a given date more efficiently, without compromising response times.

While cursor pagination is now available, it does not affect any existing behaviors. To use cursor pagination, instead of passing lastUpdate as query parameters, users will need to pass next or previous, along with count and type.

  • next or previous: These represent the cursor pointers indicating whether the query should retrieve items from a later or earlier point in time. The cursor value must be the number of milliseconds, as it follows Date getTime().
  • count: Specifies the number of records to return.
  • type: With the introduction of cursors, both updated and deleted messages cannot be retrieved in the same response. Users must specify whether they want to retrieve DELETED (for deleted messages) or UPDATED (for updated messages, which is the default use case).

Notes:

  • In the future, it might be worth considering isolating this functionality into a separate route. However, for now, the current implementation ensures no conflicts or breaking changes, and the route’s signature remains unchanged.
  • This implementation has been tested to ensure that existing users relying on lastUpdate will continue to have the same experience, with no changes required on their end.
  • Keep in mind that while performance is acceptable for now, there may be opportunities to optimize database indexes further. Pagination has been a missing feature, so addressing it was a high priority.
  • This change is especially beneficial for users who frequently work with large volumes of messages, such as when a username with a high message count in a room is changed, as cursor pagination offers a more efficient way to paginate through results.

Copy link
Contributor

dionisio-bot bot commented Sep 12, 2024

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

Copy link

changeset-bot bot commented Sep 12, 2024

⚠️ No Changeset found

Latest commit: 465c8b8

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

github-actions bot commented Sep 12, 2024

PR Preview Action v1.4.8
🚀 Deployed preview to https://RocketChat.github.io/Rocket.Chat/pr-preview/pr-33273/
on branch gh-pages at 2024-10-28 16:49 UTC

Copy link

codecov bot commented Sep 12, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 59.68%. Comparing base (0f21fa0) to head (01a21e1).
Report is 16 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #33273      +/-   ##
===========================================
- Coverage    59.79%   59.68%   -0.12%     
===========================================
  Files         2548     2551       +3     
  Lines        63412    63029     -383     
  Branches     14267    14123     -144     
===========================================
- Hits         37920    37617     -303     
+ Misses       23076    22996      -80     
  Partials      2416     2416              
Flag Coverage Δ
unit 76.91% <ø> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

@ricardogarim ricardogarim marked this pull request as ready for review September 16, 2024 11:37
@ricardogarim ricardogarim requested review from a team as code owners September 16, 2024 11:37
Copy link
Member

@MarcosSpessatto MarcosSpessatto left a comment

Choose a reason for hiding this comment

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

Let's add a changeset please.

@@ -79,28 +79,42 @@ API.v1.addRoute(
{ authRequired: true },
{
async get() {
const { roomId, lastUpdate } = this.queryParams;
const { roomId, lastUpdate, count, next, previous, type } = this.queryParams;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't we validate the type of these new parameters as well? AJV maybe? 🤔

});
const response = lastUpdate
? await handleWithoutPagination(rid, lastUpdate)
: await handleCursorPagination(type ?? 'UPDATED', rid, count, next, previous);
Copy link
Member

Choose a reason for hiding this comment

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

Why are we using Updated as default?

return null;
}

function popMessagesFromArray(messages: IMessage[], count?: number) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we could pop the message directly there, since it's not being reused, we should not create this function.

}>;
}
}

function extractTimestampFromCursor(cursor: string): Date {
Copy link
Member

Choose a reason for hiding this comment

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

Let's please add unit tests for this function.

return new Date(parseInt(cursor, 10));
}

function mountCursorQuery({ next, previous, count }: { next?: string; previous?: string; count: number }): {
Copy link
Member

Choose a reason for hiding this comment

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

Let's please add unit tests for this function.

return { query: { $gt: new Date(0) }, options };
}

function mountCursorFromMessage(message: IMessage & { _deletedAt?: Date }, type: 'UPDATED' | 'DELETED'): string {
Copy link
Member

Choose a reason for hiding this comment

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

Let's please add unit tests for this function.

throw new Meteor.Error('error-cursor-not-found', 'Cursor not found', { method: 'messages/get' });
}

function mountNextCursor(messages: IMessage[], type: CursorPaginationType, next?: string, previous?: string): string | null {
Copy link
Member

Choose a reason for hiding this comment

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

Let's please add unit tests for this function.

return null;
}

function mountPreviousCursor(messages: IMessage[], type: CursorPaginationType, count?: number, next?: string): string | null {
Copy link
Member

Choose a reason for hiding this comment

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

Let's please add unit tests for this function.

.end(done);
});

it('should return an error when the neither "lastUpdate", "next" or "previous" parameter is sent', (done) => {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
it('should return an error when the neither "lastUpdate", "next" or "previous" parameter is sent', (done) => {
it('should return an error when neither "lastUpdate", "next" or "previous" parameter is sent', (done) => {

Copy link
Member

Choose a reason for hiding this comment

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

Probably this is an old problem, but we are not using this validation on the endpoint 😶

@scuciatto scuciatto added this to the 7.1.0 milestone Oct 28, 2024
@ricardogarim ricardogarim requested review from a team as code owners October 28, 2024 16:41
@ricardogarim ricardogarim force-pushed the feat/add-cursor-pagination-support-on-syncMessages branch from 1ee2ef8 to 465c8b8 Compare October 28, 2024 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants