Extract Ci::Build::AutoRetry class

Summary

Extract Auto-retry domain concept out of Ci::Build where it exists beside normal retry capabilities. This could be easily confused with concepts such as retry and retryable? which are actions that a user can take regardless of the auto-retry logic.

Improvements

class Ci::Build::AutoRetry
  DEFAULT_RETRIES = {
    scheduler_failure: 2
  }.freeze

  def initialize(build)
    @build = build
  end

  def allowed?
    # I feel this is an invariant that is not captured today.
    # are we allowed to auto-retry something that is not retryable?
    return false unless build.retryable?

    # rest of Ci::Build#retry_failure? implementation
  end

  private

  def retry_failure?
  end

  def options_retries_max
  end

  def options_retry_when
  end
 
  def retry_on_reason_or_always?
  end

  def options_retry
  end
end

Usage in Ci::Build

class Ci::Build
  state_machine :status do 
    # ...
  
    after_transition any => [:failed] do |build|
      next unless build.project

      if build.auto_retry?
        begin
          Ci::Build.retry(build, build.user)
        rescue Gitlab::Access::AccessDeniedError => ex
          Rails.logger.error "Unable to auto-retry job #{build.id}: #{ex}" # rubocop:disable Gitlab/RailsLogger
        end
      end
    end
  end

  def auto_retry?
    AutoRetry.new(self).allowed?
  end
end

Risks

Involved components

Optional: Intended side effects

Optional: Missing test coverage

Assignee Loading
Time tracking Loading