Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/graphql/pagination')
-rw-r--r--lib/gitlab/graphql/pagination/active_record_array_connection.rb90
-rw-r--r--lib/gitlab/graphql/pagination/keyset/connection.rb4
-rw-r--r--lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb17
3 files changed, 106 insertions, 5 deletions
diff --git a/lib/gitlab/graphql/pagination/active_record_array_connection.rb b/lib/gitlab/graphql/pagination/active_record_array_connection.rb
new file mode 100644
index 00000000000..9e40f79b2fd
--- /dev/null
+++ b/lib/gitlab/graphql/pagination/active_record_array_connection.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+# Connection for an array of Active Record instances.
+# Resolvers needs to handle cursors (before and after).
+# This connection will handle (first and last).
+# Supports batch loaded items.
+# Expects the array to use a fixed DESC order. This is similar to
+# ExternallyPaginatedArrayConnection.
+module Gitlab
+ module Graphql
+ module Pagination
+ class ActiveRecordArrayConnection < GraphQL::Pagination::ArrayConnection
+ include ::Gitlab::Graphql::ConnectionCollectionMethods
+ prepend ::Gitlab::Graphql::ConnectionRedaction
+
+ delegate :<<, to: :items
+
+ def nodes
+ load_nodes
+
+ @nodes
+ end
+
+ def next_page?
+ load_nodes
+
+ if before
+ true
+ elsif first
+ limit_value < items.size
+ else
+ false
+ end
+ end
+
+ def previous_page?
+ load_nodes
+
+ if after
+ true
+ elsif last
+ limit_value < items.size
+ else
+ false
+ end
+ end
+
+ # see https://graphql-ruby.org/pagination/custom_connections#connection-wrapper
+ alias_method :has_next_page, :next_page?
+ alias_method :has_previous_page, :previous_page?
+
+ def cursor_for(item)
+ # item could be a batch loaded item. Sync it to have the id.
+ cursor = { 'id' => Gitlab::Graphql::Lazy.force(item).id.to_s }
+ encode(cursor.to_json)
+ end
+
+ # Part of the implied interface for default objects for BatchLoader: objects must be clonable
+ def dup
+ self.class.new(
+ items.dup,
+ first: first,
+ after: after,
+ max_page_size: max_page_size,
+ last: last,
+ before: before
+ )
+ end
+
+ private
+
+ def limit_value
+ # note: only first _or_ last can be specified, not both
+ @limit_value ||= [first, last, max_page_size].compact.min
+ end
+
+ def load_nodes
+ @nodes ||= begin
+ limited_nodes = items
+
+ limited_nodes = limited_nodes.first(first) if first
+ limited_nodes = limited_nodes.last(last) if last
+
+ limited_nodes
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/pagination/keyset/connection.rb b/lib/gitlab/graphql/pagination/keyset/connection.rb
index 61903c566f0..c284160e539 100644
--- a/lib/gitlab/graphql/pagination/keyset/connection.rb
+++ b/lib/gitlab/graphql/pagination/keyset/connection.rb
@@ -14,10 +14,6 @@
# Issue.order(created_at: :asc).order(:id)
# Issue.order(due_date: :asc)
#
-# You can also use `Gitlab::Database.nulls_last_order`:
-#
-# Issue.reorder(::Gitlab::Database.nulls_last_order('due_date', 'DESC'))
-#
# It will tolerate non-attribute ordering, but only attributes determine the cursor.
# For example, this is legitimate:
#
diff --git a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
index e8335a3c79c..bf9b73d918a 100644
--- a/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
+++ b/lib/gitlab/graphql/pagination/keyset/generic_keyset_pagination.rb
@@ -73,9 +73,24 @@ module Gitlab
strong_memoize(:generic_keyset_pagination_items) do
rebuilt_items_with_keyset_order, success = Gitlab::Pagination::Keyset::SimpleOrderBuilder.build(original_items)
- success ? rebuilt_items_with_keyset_order : original_items
+ if success
+ rebuilt_items_with_keyset_order
+ else
+ if original_items.is_a?(ActiveRecord::Relation)
+ old_keyset_pagination_usage.increment({ model: original_items.model.to_s })
+ end
+
+ original_items
+ end
end
end
+
+ def old_keyset_pagination_usage
+ @old_keyset_pagination_usage ||= Gitlab::Metrics.counter(
+ :old_keyset_pagination_usage,
+ 'The number of times the old keyset pagination code was used'
+ )
+ end
end
end
end