diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 21:42:06 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-20 21:42:06 +0300 |
commit | 6e4e1050d9dba2b7b2523fdd1768823ab85feef4 (patch) | |
tree | 78be5963ec075d80116a932011d695dd33910b4e /lib/gitlab/pagination | |
parent | 1ce776de4ae122aba3f349c02c17cebeaa8ecf07 (diff) |
Add latest changes from gitlab-org/gitlab@13-3-stable-ee
Diffstat (limited to 'lib/gitlab/pagination')
-rw-r--r-- | lib/gitlab/pagination/gitaly_keyset_pager.rb | 54 | ||||
-rw-r--r-- | lib/gitlab/pagination/keyset/header_builder.rb | 45 | ||||
-rw-r--r-- | lib/gitlab/pagination/keyset/request_context.rb | 27 |
3 files changed, 105 insertions, 21 deletions
diff --git a/lib/gitlab/pagination/gitaly_keyset_pager.rb b/lib/gitlab/pagination/gitaly_keyset_pager.rb new file mode 100644 index 00000000000..651e3d5a807 --- /dev/null +++ b/lib/gitlab/pagination/gitaly_keyset_pager.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module Gitlab + module Pagination + class GitalyKeysetPager + attr_reader :request_context, :project + delegate :params, to: :request_context + + def initialize(request_context, project) + @request_context = request_context + @project = project + end + + # It is expected that the given finder will respond to `execute` method with `gitaly_pagination: true` option + # and supports pagination via gitaly. + def paginate(finder) + return paginate_via_gitaly(finder) if keyset_pagination_enabled? + + branches = ::Kaminari.paginate_array(finder.execute) + Gitlab::Pagination::OffsetPagination + .new(request_context) + .paginate(branches) + end + + private + + def keyset_pagination_enabled? + Feature.enabled?(:branch_list_keyset_pagination, project) && params[:pagination] == 'keyset' + end + + def paginate_via_gitaly(finder) + finder.execute(gitaly_pagination: true).tap do |records| + apply_headers(records) + end + end + + def apply_headers(records) + if records.count == params[:per_page] + Gitlab::Pagination::Keyset::HeaderBuilder + .new(request_context) + .add_next_page_header( + query_params_for(records.last) + ) + end + end + + def query_params_for(record) + # NOTE: page_token is name for now, but it could be dynamic if we have other gitaly finders + # that is based on something other than name + { page_token: record.name } + end + end + end +end diff --git a/lib/gitlab/pagination/keyset/header_builder.rb b/lib/gitlab/pagination/keyset/header_builder.rb new file mode 100644 index 00000000000..69c468207f6 --- /dev/null +++ b/lib/gitlab/pagination/keyset/header_builder.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module Gitlab + module Pagination + module Keyset + class HeaderBuilder + attr_reader :request_context + delegate :params, :header, :request, to: :request_context + + def initialize(request_context) + @request_context = request_context + end + + def add_next_page_header(query_params) + link = next_page_link(page_href(query_params)) + header('Links', link) + header('Link', link) + end + + private + + def next_page_link(href) + %(<#{href}>; rel="next") + end + + def page_href(query_params) + base_request_uri.tap do |uri| + uri.query = updated_params(query_params).to_query + end.to_s + end + + def base_request_uri + @base_request_uri ||= URI.parse(request.url).tap do |uri| + uri.host = Gitlab.config.gitlab.host + uri.port = Gitlab.config.gitlab.port + end + end + + def updated_params(query_params) + params.merge(query_params) + end + end + end + end +end diff --git a/lib/gitlab/pagination/keyset/request_context.rb b/lib/gitlab/pagination/keyset/request_context.rb index 070fa844347..ba17fb03681 100644 --- a/lib/gitlab/pagination/keyset/request_context.rb +++ b/lib/gitlab/pagination/keyset/request_context.rb @@ -24,9 +24,11 @@ module Gitlab end def apply_headers(next_page) - link = pagination_links(next_page) - request.header('Links', link) - request.header('Link', link) + Gitlab::Pagination::Keyset::HeaderBuilder + .new(request) + .add_next_page_header( + query_params_for(next_page) + ) end private @@ -63,25 +65,8 @@ module Gitlab end end - def page_href(page) - base_request_uri.tap do |uri| - uri.query = query_params_for(page).to_query - end.to_s - end - - def pagination_links(next_page) - %(<#{page_href(next_page)}>; rel="next") - end - - def base_request_uri - @base_request_uri ||= URI.parse(request.request.url).tap do |uri| - uri.host = Gitlab.config.gitlab.host - uri.port = Gitlab.config.gitlab.port - end - end - def query_params_for(page) - request.params.merge(lower_bounds_params(page)) + lower_bounds_params(page) end end end |