summaryrefslogtreecommitdiff
path: root/lib/gitlab/graphql/loaders/issuable_loader.rb
blob: 1cc0fbe215f3d2c1efe985dac0c8783851af8253 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# frozen_string_literal: true

module Gitlab
  module Graphql
    module Loaders
      class IssuableLoader
        attr_reader :parent, :issuable_finder

        BatchKey = Struct.new(:parent, :finder_class, :current_user)

        def initialize(parent, issuable_finder)
          @parent = parent
          @issuable_finder = issuable_finder
        end

        def batching_find_all(&with_query)
          if issuable_finder.params.keys == ['iids']
            batch_load_issuables(issuable_finder.params[:iids], with_query)
          else
            post_process(find_all, with_query)
          end
        end

        def find_all
          issuable_finder.params[parent_param] = parent if parent

          issuable_finder.execute
        end

        private

        def parent_param
          case parent
          when Project
            :project_id
          when Group
            :group_id
          else
            raise "Unexpected parent: #{parent.class}"
          end
        end

        def post_process(query, with_query)
          if with_query
            with_query.call(query)
          else
            query
          end
        end

        def batch_load_issuables(iids, with_query)
          Array.wrap(iids).map { |iid| batch_load(iid, with_query) }
        end

        def batch_load(iid, with_query)
          return if parent.nil?

          BatchLoader::GraphQL
            .for([parent_param, iid.to_s])
            .batch(key: batch_key) do |params, loader, args|
              batch_key = args[:key]
              user = batch_key.current_user

              params.group_by(&:first).each do |key, group|
                iids = group.map(&:second).uniq
                args = { key => batch_key.parent, iids: iids }
                query = batch_key.finder_class.new(user, args).execute

                post_process(query, with_query).each do |item|
                  loader.call([key, item.iid.to_s], item)
                end
              end
            end
        end

        def batch_key
          BatchKey.new(parent, issuable_finder.class, issuable_finder.current_user)
        end
      end
    end
  end
end