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

object_importer.rb « github_import « gitlab « concerns « workers « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: da0a54c79f838865dccda6785b4d284467617d8e (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# frozen_string_literal: true

module Gitlab
  module GithubImport
    # ObjectImporter defines the base behaviour for every Sidekiq worker that
    # imports a single resource such as a note or pull request.
    module ObjectImporter
      extend ActiveSupport::Concern

      included do
        include ApplicationWorker

        include GithubImport::Queue
        include ReschedulingMethods

        feature_category :importers
        worker_has_external_dependencies!

        sidekiq_options retry: 5
        sidekiq_retries_exhausted do |msg|
          args = msg['args']
          jid = msg['jid']

          # If a job is being exhausted we still want to notify the
          # Gitlab::Import::AdvanceStageWorker to prevent the entire import from getting stuck
          if args.length == 3 && (key = args.last) && key.is_a?(String)
            JobWaiter.notify(key, jid, ttl: Gitlab::Import::JOB_WAITER_TTL)
          end
        end
      end

      NotRetriableError = Class.new(StandardError)

      # project - An instance of `Project` to import the data into.
      # client - An instance of `Gitlab::GithubImport::Client`
      # hash - A Hash containing the details of the object to import.
      def import(project, client, hash)
        if project.import_state&.completed?
          info(
            project.id,
            message: 'Project import is no longer running. Stopping worker.',
            import_status: project.import_state.status
          )

          return
        end

        object = representation_class.from_json_hash(hash)

        # To better express in the logs what object is being imported.
        self.github_identifiers = object.github_identifiers
        info(project.id, message: 'starting importer')

        importer_class.new(object, project, client).execute

        increment_object_counter(object, project) if increment_object_counter?(object)

        info(project.id, message: 'importer finished')
      rescue ActiveRecord::RecordInvalid, NotRetriableError, NoMethodError => e
        # We do not raise exception to prevent job retry
        track_exception(project, e)
      rescue UserFinder::FailedToObtainLockError
        warn(project.id, message: 'Failed to obtaing lock for user finder. Retrying later.')

        raise
      rescue StandardError => e
        track_and_raise_exception(project, e)
      end

      def increment_object_counter?(_object)
        true
      end

      def increment_object_counter(_object, project)
        Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :imported)
      end

      def object_type
        raise NotImplementedError
      end

      # Returns the representation class to use for the object. This class must
      # define the class method `from_json_hash`.
      def representation_class
        raise NotImplementedError
      end

      # Returns the class to use for importing the object.
      def importer_class
        raise NotImplementedError
      end

      private

      attr_accessor :github_identifiers

      def info(project_id, extra = {})
        Logger.info(log_attributes(project_id, extra))
      end

      def warn(project_id, extra = {})
        Logger.warn(log_attributes(project_id, extra))
      end

      def log_attributes(project_id, extra = {})
        extra.merge(
          project_id: project_id,
          importer: importer_class.name,
          external_identifiers: github_identifiers
        )
      end

      def track_exception(project, exception, fail_import: false)
        external_identifiers = github_identifiers || {}
        external_identifiers[:object_type] ||= object_type&.to_s

        Gitlab::Import::ImportFailureService.track(
          project_id: project.id,
          error_source: importer_class.name,
          exception: exception,
          fail_import: fail_import,
          external_identifiers: external_identifiers
        )
      end

      def track_and_raise_exception(project, exception, fail_import: false)
        track_exception(project, exception, fail_import: fail_import)

        raise(exception)
      end
    end
  end
end