Module: Gitlab::OptimisticLocking

Constant Summary collapse

MAX_RETRIES =
100

Class Method Summary collapse

Class Method Details

.log_optimistic_lock_retries(name:, retry_attempts:, start_time:) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/gitlab/optimistic_locking.rb', line 39

def log_optimistic_lock_retries(name:, retry_attempts:, start_time:)
  return unless retry_attempts > 0

  elapsed_time = Gitlab::Metrics::System.monotonic_time - start_time

  retry_lock_logger.info(
    message: "Optimistic Lock released with retries",
    name: name,
    retries: retry_attempts,
    time_s: elapsed_time)
end

.retry_lock(subject, max_retries = MAX_RETRIES, name:, &block) ⇒ Object Also known as: retry_optimistic_lock



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
# File 'lib/gitlab/optimistic_locking.rb', line 9

def retry_lock(subject, max_retries = MAX_RETRIES, name:, &block)
  start_time = Gitlab::Metrics::System.monotonic_time
  retry_attempts = 0

  # prevent scope override, see https://gitlab.com/gitlab-org/gitlab/-/issues/391186
  klass = subject.is_a?(ActiveRecord::Relation) ? subject.klass : subject.class

  begin
    klass.transaction do
      yield(subject)
    end
  rescue ActiveRecord::StaleObjectError
    raise unless retry_attempts < max_retries

    subject.reset

    retry_attempts += 1
    retry
  ensure
    retry_lock_histogram.observe({}, retry_attempts)

    log_optimistic_lock_retries(
      name: name,
      retry_attempts: retry_attempts,
      start_time: start_time)
  end
end

.retry_lock_histogramObject



55
56
57
58
59
60
61
62
63
# File 'lib/gitlab/optimistic_locking.rb', line 55

def retry_lock_histogram
  @retry_lock_histogram ||=
    Gitlab::Metrics.histogram(
      :gitlab_optimistic_locking_retries,
      'Number of retry attempts to execute optimistic retry lock',
      {},
      [0, 1, 2, 3, 5, 10, 50]
    )
end

.retry_lock_loggerObject



51
52
53
# File 'lib/gitlab/optimistic_locking.rb', line 51

def retry_lock_logger
  @retry_lock_logger ||= Gitlab::Services::Logger.build
end