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

Replace page numbers with ID based selection for trace indexes #4089

Merged
merged 1 commit into from
Jul 26, 2023

Conversation

tomhughes
Copy link
Member

@tomhughes tomhughes commented Jul 12, 2023

This allows us to avoid horribly inefficient queries when people try and fetch ever large page numbers for the trace list forcing us to read ever large number of records.

It also means the URLs remain stable and will always show more or less the same traces, modulo any changes when traces are deleted, whereas page numbers change constantly over time.

Copy link
Collaborator

@gravitystorm gravitystorm left a comment

Choose a reason for hiding this comment

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

Overall I'm happy with the idea of moving to cursor-based pagination. I'd like to do the same for all of our existing offset-based pagination, since it all has the same problems as here (degraded performance for increasing pagenumbers, highly unstable urls, etc).

In addition to the line-by-line comments, I wonder if rather than trying to get the logic and edge cases right (and making all the logic etc resuable across controllers) I wonder if we are better off finding a gem that does what we want. There's a few different ones that I've found, such as rails_cursor_pagination, pagy_cursor, etc

<li class="page-item">
<%= link_to t(".newer"), params.merge(:page => page - 1), :class => "page-link" %>
<%= link_to t(".newer"), params.merge(:min_id => traces.first.id + 1, :max_id => nil), :class => "page-link" %>
Copy link
Collaborator

Choose a reason for hiding this comment

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

The logic here isn't working quite right. If I go to the final page of traces on my system (i.e. press "older" a few times) then I get a link to newer traces e.g. "min_id=3". But that link shows me the first page of traces, not the second-to-last.

Since traces are reverse sorted, traces.where(id >= 3).order_by(id desc).limit(25) returns traces that are max(id) to max(id)-25 e.g. 1003 to 978, instead of 27 to 3 which is what was intended.

app/views/traces/_trace_paging_nav.html.erb Show resolved Hide resolved
</li>
<!-- my traces -->
<li class="nav-item">
<%= link_to t(".my_traces"), { :action => "mine", :page => nil }, { :class => "nav-link active" } %>
<%= link_to t(".my_traces"), { :action => "mine", :max_id => nil }, { :class => "nav-link active" } %>
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think any of these :max_id => nil are needed, since the link is being built from scratch (other links are built from merging with existing params elsewhere).

Or if I've misunderstood, and they are necessary, then I think a :min_id => nil would be needed too.

test/controllers/traces_controller_test.rb Show resolved Hide resolved
@@ -54,14 +54,16 @@ def index

@traces = @traces.tagged(params[:tag]) if params[:tag]

@params = params.permit(:display_name, :tag)
@params = params.permit(:display_name, :tag, :min_id, :max_id)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Most implementations I've seen use "before" and "after" as the parameters. I'm not sure why, but maybe it makes it easier when reasoning about id sort order? (see other comment)

Copy link
Member Author

Choose a reason for hiding this comment

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

I based max_id on what we were already doing doing for changesets in the history view but I wasn't especially keen on it.

@tomhughes
Copy link
Member Author

I've pushed a new version that I think addresses all your review comments.

I did look at the possibility of using a gem but I'm not convinced there's anything that's useful for various reasons.

In many ways pagy_cursor looks excellent, especially since it's an extension to pagy which provides nice view helpers and would be good to replace our existing paging code for places where we do real paging. The problem is that it doesn't really integrate with pagy in any meaningful way and you can't use the pagy navigation helpers as Uysim/pagy-cursor#21 makes clear. It's not entirely their fault as pagy would need changes to allow it to support cursor based paging but there doesn't seem to be any effort to properly integrate them.

As to rails_cursor_pagination there is the issue of the rather ugly cursors but we could live with that - you could even argue it's an advantage. There's a killer bug at the moment though (xing/rails_cursor_pagination#132) in that even if you disable totals it still does the query when working our whether next/previous links are needed!

@gravitystorm gravitystorm merged commit 30201e9 into openstreetmap:master Jul 26, 2023
@tomhughes tomhughes deleted the trace-paging branch July 26, 2023 16:00
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