summaryrefslogtreecommitdiff
path: root/lib/gitlab/github_import/issuable_finder.rb
blob: e7a1b7b3368ba78a838e835b020c66648c97b7c8 (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
83
84
85
86
87
88
89
90
91
# frozen_string_literal: true

module Gitlab
  module GithubImport
    # IssuableFinder can be used for caching and retrieving database IDs for
    # issuable objects such as issues and pull requests. By caching these IDs we
    # remove the need for running a lot of database queries when importing
    # GitHub projects.
    class IssuableFinder
      attr_reader :project, :object

      # The base cache key to use for storing/retrieving issuable IDs.
      CACHE_KEY = 'github-import/issuable-finder/%{project}/%{type}/%{iid}'

      # project - An instance of `Project`.
      # object - The object to look up or set a database ID for.
      def initialize(project, object)
        @project = project
        @object = object
      end

      # Returns the database ID for the object.
      #
      # This method will return `nil` if no ID could be found.
      def database_id
        val = Gitlab::Cache::Import::Caching.read(cache_key, timeout: timeout)

        val.to_i if val.present?
      end

      # Associates the given database ID with the current object.
      #
      # database_id - The ID of the corresponding database row.
      def cache_database_id(database_id)
        Gitlab::Cache::Import::Caching.write(cache_key, database_id, timeout: timeout)
      end

      private

      def cache_key
        CACHE_KEY % {
          project: project.id,
          type: cache_key_type,
          iid: cache_key_iid
        }
      end

      # Returns the identifier to use for cache keys.
      #
      # For issues and pull requests this will be "Issue" or "MergeRequest"
      # respectively. For diff notes this will return "MergeRequest", for
      # regular notes it will either return "Issue" or "MergeRequest" depending
      # on what type of object the note belongs to.
      def cache_key_type
        if object.respond_to?(:issuable_type)
          object.issuable_type
        elsif object.respond_to?(:noteable_type)
          object.noteable_type
        else
          raise(
            TypeError,
            "Instances of #{object.class} are not supported"
          )
        end
      end

      def cache_key_iid
        if object.respond_to?(:noteable_id)
          object.noteable_id
        elsif object.respond_to?(:iid)
          object.iid
        elsif object.respond_to?(:issuable_id)
          object.issuable_id
        else
          raise(
            TypeError,
            "Instances of #{object.class} are not supported"
          )
        end
      end

      def timeout
        if project.group.present? && ::Feature.enabled?(:github_importer_single_endpoint_notes_import, project.group, type: :ops)
          Gitlab::Cache::Import::Caching::LONGER_TIMEOUT
        else
          Gitlab::Cache::Import::Caching::TIMEOUT
        end
      end
    end
  end
end