Skip to content

Avoid another (cached) query for next link #55

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

Merged
merged 5 commits into from
Nov 6, 2023

Conversation

lewispb
Copy link
Member

@lewispb lewispb commented Nov 6, 2023

Page#records already returns the records for the current page, so #next_param can use that to determine the last record for the next param, used in the Link header.

This is a performance optimization.

This avoids another query, albeit one that usually hits the Active Record Query Cache. The Query Cache is not always the most performant option.

cc @basecamp/sip

Rather than issue another query for the next link, rely on the records
already loaded
@@ -20,7 +20,11 @@ def from(scope)
end

def next_param(scope)
Cursor.encode page_number: page_number + 1, values: from(scope).last&.slice(*attributes) || {}
if scope.order_values.none? && scope.limit_value.nil?
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need this check?

Copy link
Member Author

Choose a reason for hiding this comment

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

The scope argument can be a full set of records, or now just a portion and the method supports both.

This check supports the full set of records. Although we now never call this method with a full set of records internally to Geared Pagination, there's a test for it and I wasn't sure about how much of this should be considered a public API?

test "next param" do
create_recordings
param = GearedPagination::PortionAtCursor.new(ordered_by: ORDERS).next_param(Recording.all)
assert_equal GearedPagination::Cursor.encode(page_number: 2, values: { number: 106, id: 106 }), param
param = GearedPagination::PortionAtCursor.new(
cursor: GearedPagination::Cursor.decode(param), ordered_by: ORDERS).next_param(Recording.all)
assert_equal GearedPagination::Cursor.encode(page_number: 3, values: { number: 76, id: 76 }), param
param = GearedPagination::PortionAtCursor.new(
cursor: GearedPagination::Cursor.decode(param), ordered_by: ORDERS).next_param(Recording.all)
assert_equal GearedPagination::Cursor.encode(page_number: 4, values: { number: 26, id: 26 }), param
end

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense thanks! Could extract a method for the check?

Copy link
Member Author

Choose a reason for hiding this comment

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

Pushed a3f9008 to avoid the check, by explicitly passing a portion in a kwarg without breaking the existing API.

Copy link
Member Author

Choose a reason for hiding this comment

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

Pushed 22e140b as per your idea @djmb to memoize instead. Thanks!

@lewispb lewispb merged commit d2cae96 into master Nov 6, 2023
@lewispb lewispb deleted the avoid-another-query-for-next-link branch November 6, 2023 19:10
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.

2 participants