Read about our upcoming Code of Conduct on this issue

project_import_state.rb 2.49 KB
Newer Older
1
2
# frozen_string_literal: true

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
class ProjectImportState < ActiveRecord::Base
  include AfterCommitQueue

  self.table_name = "project_mirror_data"

  belongs_to :project, inverse_of: :import_state

  validates :project, presence: true

  state_machine :status, initial: :none do
    event :schedule do
      transition [:none, :finished, :failed] => :scheduled
    end

    event :force_start do
      transition [:none, :finished, :failed] => :started
    end

    event :start do
      transition scheduled: :started
    end

    event :finish do
      transition started: :finished
    end

    event :fail_op do
      transition [:scheduled, :started] => :failed
    end

    state :scheduled
    state :started
    state :finished
    state :failed

    after_transition [:none, :finished, :failed] => :scheduled do |state, _|
      state.run_after_commit do
        job_id = project.add_import_job
        update(jid: job_id) if job_id
      end
    end

    after_transition started: :finished do |state, _|
      project = state.project

      project.reset_cache_and_import_attrs

      if Gitlab::ImportSources.importer_names.include?(project.import_type) && project.repo_exists?
51
        # rubocop: disable CodeReuse/ServiceClass
52
53
54
        state.run_after_commit do
          Projects::AfterImportService.new(project).execute
        end
55
        # rubocop: enable CodeReuse/ServiceClass
56
57
58
      end
    end
  end
59
60
61
62
63
64
65
66
67
68
69
70
71

  def mark_as_failed(error_message)
    original_errors = errors.dup
    sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)

    fail_op

    update_column(:last_error, sanitized_message)
  rescue ActiveRecord::ActiveRecordError => e
    Rails.logger.error("Error setting import status to failed: #{e.message}. Original error: #{sanitized_message}")
  ensure
    @errors = original_errors
  end
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

  alias_method :no_import?, :none?

  def in_progress?
    started? || scheduled?
  end

  def started?
    # import? does SQL work so only run it if it looks like there's an import running
    status == 'started' && project.import?
  end

  def remove_jid
    return unless jid

    Gitlab::SidekiqStatus.unset(jid)

    update_column(:jid, nil)
  end

  # Refreshes the expiration time of the associated import job ID.
  #
  # This method can be used by asynchronous importers to refresh the status,
  # preventing the StuckImportJobsWorker from marking the import as failed.
  def refresh_jid_expiration
    return unless jid

    Gitlab::SidekiqStatus.set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
  end
101
end