Class: Issues::RelativePositionRebalancingService

Inherits:
Object
  • Object
show all
Defined in:
app/services/issues/relative_position_rebalancing_service.rb

Constant Summary collapse

UPDATE_BATCH_SIZE =
100
PREFETCH_ISSUES_BATCH_SIZE =
10_000
SMALLEST_BATCH_SIZE =
5
RETRIES_LIMIT =
3
TooManyConcurrentRebalances =
Class.new(StandardError)

Instance Method Summary collapse

Constructor Details

#initialize(projects) ⇒ RelativePositionRebalancingService

Returns a new instance of RelativePositionRebalancingService.



12
13
14
15
16
# File 'app/services/issues/relative_position_rebalancing_service.rb', line 12

def initialize(projects)
  @projects_collection = (projects.is_a?(Array) ? Project.id_in(projects) : projects).select(:id).projects_order_id_asc
  @root_namespace = @projects_collection.select(:namespace_id).reorder(nil).take.root_namespace # rubocop:disable CodeReuse/ActiveRecord
  @caching = ::Gitlab::Issues::Rebalancing::State.new(@root_namespace, @projects_collection)
end

Instance Method Details

#executeObject



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
# File 'app/services/issues/relative_position_rebalancing_service.rb', line 18

def execute
  # Given can_start_rebalance? and track_new_running_rebalance are not atomic
  # it can happen that we end up with more than Rebalancing::State::MAX_NUMBER_OF_CONCURRENT_REBALANCES running.
  # Considering the number of allowed Rebalancing::State::MAX_NUMBER_OF_CONCURRENT_REBALANCES is small we should be ok,
  # but should be something to consider if we'd want to scale this up.
  error_message = "#{caching.concurrent_running_rebalances_count} concurrent re-balances currently running"
  raise TooManyConcurrentRebalances, error_message unless caching.can_start_rebalance?

  block_issue_repositioning! unless root_namespace.issue_repositioning_disabled?
  caching.track_new_running_rebalance
  index = caching.get_current_index

  loop do
    issue_ids = get_issue_ids(index, PREFETCH_ISSUES_BATCH_SIZE)
    pairs_with_index = assign_indexes(issue_ids, index)

    pairs_with_index.each_slice(UPDATE_BATCH_SIZE) do |pairs_batch|
      update_positions_with_retry(pairs_batch, 're-balance issue positions in batches ordered by position')
    end

    index = caching.get_current_index

    break if index >= caching.issue_count - 1
  end

  caching.cleanup_cache
  unblock_issue_repositioning!
end