Class: Gitlab::Graphql::Pagination::ClickHouseConnection

Inherits:
GraphQL::Pagination::Connection
  • Object
show all
Includes:
Utils::StrongMemoize
Defined in:
lib/gitlab/graphql/pagination/click_house_connection.rb

Overview

rubocop: disable CodeReuse/ActiveRecord – requires AR methods to build the keyset pagination conditions

Direct Known Subclasses

ClickHouseAggregatedConnection

Constant Summary collapse

TIME_PATTERN =

Timestamps are stored with 6 digit microseconds precision in both PG and in CH (our schema)

"%Y-%m-%d %H:%M:%S.%6N"

Instance Method Summary collapse

Instance Method Details

#cursor_for(item) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/gitlab/graphql/pagination/click_house_connection.rb', line 52

def cursor_for(item)
  raw_cursor = @items.manager.ast.orders.each_with_object({}) do |order, hash|
    expression_name = order.expr.name
    value = item[expression_name]
    raise "Cursor value for '#{expression_name}' is missing" if value.nil?

    hash[expression_name] = case
                            when value.is_a?(Date)
                              value.to_fs(:db)
                            when value.is_a?(Time)
                              # In ClickHouse we store timestamps in UTC
                              value.utc.strftime(TIME_PATTERN)
                            when value.is_a?(Numeric) || value.is_a?(String)
                              value
                            else
                              raise 'Unsupported type in the cursor: only Time, \
                              Numeric, and String types are supported'
                            end
  end

  encode(Gitlab::Json.dump(raw_cursor))
end

#decoded_cursor(cursor) ⇒ Object



75
76
77
78
79
# File 'lib/gitlab/graphql/pagination/click_house_connection.rb', line 75

def decoded_cursor(cursor)
  Gitlab::Json.parse(decode(cursor))
rescue JSON::ParserError
  raise Gitlab::Graphql::Errors::ArgumentError, 'Invalid cursor given'
end

#has_next_pageObject



36
37
38
39
40
41
42
43
44
# File 'lib/gitlab/graphql/pagination/click_house_connection.rb', line 36

def has_next_page
  if before
    true
  elsif first
    limited_nodes.size > limit_value
  else
    false
  end
end

#has_previous_pageObject

rubocop: disable Naming/PredicateName – methods required by PageInfo relay.dev/graphql/connections.htm#sec-undefined.PageInfo.Fields



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/gitlab/graphql/pagination/click_house_connection.rb', line 15

def has_previous_page
  if after
    # If `after` is specified, that points to a specific record,
    # even if it's the first one.  Since we're asking for `after`,
    # then the specific record we're pointing to is in the
    # previous page
    true
  elsif last
    limited_nodes
    !!@has_previous_page_cache
  else
    # Key thing to remember.  When `before` is specified (and no `last`),
    # the spec says return _all_ edges minus anything after the `before`.
    # Which means the returned list starts at the very first record.
    # Then the max_page kicks in, and returns the first max_page items.
    # Because of this, `has_previous_page` will be false
    false
  end
end

#nodesObject

rubocop: enable Naming/PredicateName



48
49
50
# File 'lib/gitlab/graphql/pagination/click_house_connection.rb', line 48

def nodes
  limited_nodes.take(limit_value)
end