summaryrefslogtreecommitdiff
path: root/spec/services/issue_rebalancing_service_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/services/issue_rebalancing_service_spec.rb')
-rw-r--r--spec/services/issue_rebalancing_service_spec.rb71
1 files changed, 63 insertions, 8 deletions
diff --git a/spec/services/issue_rebalancing_service_spec.rb b/spec/services/issue_rebalancing_service_spec.rb
index 7b3d4213b24..1c7f74264b7 100644
--- a/spec/services/issue_rebalancing_service_spec.rb
+++ b/spec/services/issue_rebalancing_service_spec.rb
@@ -3,31 +3,35 @@
require 'spec_helper'
RSpec.describe IssueRebalancingService do
- let_it_be(:project) { create(:project) }
+ let_it_be(:project, reload: true) { create(:project) }
let_it_be(:user) { project.creator }
let_it_be(:start) { RelativePositioning::START_POSITION }
let_it_be(:max_pos) { RelativePositioning::MAX_POSITION }
let_it_be(:min_pos) { RelativePositioning::MIN_POSITION }
let_it_be(:clump_size) { 300 }
- let_it_be(:unclumped) do
- (0..clump_size).to_a.map do |i|
+ let_it_be(:unclumped, reload: true) do
+ (1..clump_size).to_a.map do |i|
create(:issue, project: project, author: user, relative_position: start + (1024 * i))
end
end
- let_it_be(:end_clump) do
- (0..clump_size).to_a.map do |i|
+ let_it_be(:end_clump, reload: true) do
+ (1..clump_size).to_a.map do |i|
create(:issue, project: project, author: user, relative_position: max_pos - i)
end
end
- let_it_be(:start_clump) do
- (0..clump_size).to_a.map do |i|
+ let_it_be(:start_clump, reload: true) do
+ (1..clump_size).to_a.map do |i|
create(:issue, project: project, author: user, relative_position: min_pos + i)
end
end
+ before do
+ stub_feature_flags(issue_rebalancing_with_retry: false)
+ end
+
def issues_in_position_order
project.reload.issues.reorder(relative_position: :asc).to_a
end
@@ -101,19 +105,70 @@ RSpec.describe IssueRebalancingService do
end
end
+ shared_examples 'rebalancing is retried on statement timeout exceptions' do
+ subject { described_class.new(project.issues.first) }
+
+ it 'retries update statement' do
+ call_count = 0
+ allow(subject).to receive(:run_update_query) do
+ call_count += 1
+ if call_count < 13
+ raise(ActiveRecord::QueryCanceled)
+ else
+ call_count = 0 if call_count == 13 + 16 # 16 = 17 sub-batches - 1 call that succeeded as part of 5th batch
+ true
+ end
+ end
+
+ # call math:
+ # batches start at 100 and are split in half after every 3 retries if ActiveRecord::StatementTimeout exception is raised.
+ # We raise ActiveRecord::StatementTimeout exception for 13 calls:
+ # 1. 100 => 3 calls
+ # 2. 100/2=50 => 3 calls + 3 above = 6 calls, raise ActiveRecord::StatementTimeout
+ # 3. 50/2=25 => 3 calls + 6 above = 9 calls, raise ActiveRecord::StatementTimeout
+ # 4. 25/2=12 => 3 calls + 9 above = 12 calls, raise ActiveRecord::StatementTimeout
+ # 5. 12/2=6 => 1 call + 12 above = 13 calls, run successfully
+ #
+ # so out of 100 elements we created batches of 6 items => 100/6 = 17 sub-batches of 6 or less elements
+ #
+ # project.issues.count: 900 issues, so 9 batches of 100 => 9 * (13+16) = 261
+ expect(subject).to receive(:update_positions).exactly(261).times.and_call_original
+
+ subject.execute
+ end
+ end
+
context 'when issue_rebalancing_optimization feature flag is on' do
before do
stub_feature_flags(issue_rebalancing_optimization: true)
end
it_behaves_like 'IssueRebalancingService shared examples'
+
+ context 'when issue_rebalancing_with_retry feature flag is on' do
+ before do
+ stub_feature_flags(issue_rebalancing_with_retry: true)
+ end
+
+ it_behaves_like 'IssueRebalancingService shared examples'
+ it_behaves_like 'rebalancing is retried on statement timeout exceptions'
+ end
end
- context 'when issue_rebalancing_optimization feature flag is on' do
+ context 'when issue_rebalancing_optimization feature flag is off' do
before do
stub_feature_flags(issue_rebalancing_optimization: false)
end
it_behaves_like 'IssueRebalancingService shared examples'
+
+ context 'when issue_rebalancing_with_retry feature flag is on' do
+ before do
+ stub_feature_flags(issue_rebalancing_with_retry: true)
+ end
+
+ it_behaves_like 'IssueRebalancingService shared examples'
+ it_behaves_like 'rebalancing is retried on statement timeout exceptions'
+ end
end
end