summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-10-22 14:27:13 -0400
committerNick Vatamaniuc <vatamane@apache.org>2019-10-22 16:05:38 -0400
commite943e76ea4c06a335958dbf6837c243ce00a21a7 (patch)
treee408ca88f092681eb594057dbe1b3e85acafbbbd
parentae29ffcd799b7db85f715b0106941143a4ba04aa (diff)
downloadcouchdb-replicator-job-churn-fix.tar.gz
Avoid churning replication jobs if there is enough room to run pending jobsreplicator-job-churn-fix
When rescheduling jobs, make sure to stops existing job as much as needed to make room for the pending jobs.
-rw-r--r--src/couch_replicator/src/couch_replicator_scheduler.erl36
1 files changed, 34 insertions, 2 deletions
diff --git a/src/couch_replicator/src/couch_replicator_scheduler.erl b/src/couch_replicator/src/couch_replicator_scheduler.erl
index 7fe417a53..52d362b99 100644
--- a/src/couch_replicator/src/couch_replicator_scheduler.erl
+++ b/src/couch_replicator/src/couch_replicator_scheduler.erl
@@ -760,8 +760,12 @@ rotate_jobs(State, ChurnSoFar) ->
% Reduce MaxChurn by the number of already stopped jobs in the
% current rescheduling cycle.
Churn = max(0, MaxChurn - ChurnSoFar),
- if Running =< MaxJobs ->
- StopCount = lists:min([Pending, Running, Churn]),
+ SlotsAvailable = MaxJobs - Running,
+ if SlotsAvailable >= 0 ->
+ % If there is are enough SlotsAvailable reduce StopCount to avoid
+ % unnesessarily stopping jobs. `stop_jobs/3` ignores 0 or negative
+ % values so we don't worry about that here.
+ StopCount = lists:min([Pending - SlotsAvailable, Running, Churn]),
stop_jobs(StopCount, true, State),
StartCount = max(0, MaxJobs - running_job_count()),
start_jobs(StartCount, State);
@@ -1047,6 +1051,8 @@ scheduler_test_() ->
t_stop_oldest_first(),
t_start_oldest_first(),
t_jobs_churn_even_if_not_all_max_jobs_are_running(),
+ t_jobs_dont_churn_if_there_are_available_running_slots(),
+ t_start_only_pending_jobs_do_not_churn_existing_ones(),
t_dont_stop_if_nothing_pending(),
t_max_churn_limits_number_of_rotated_jobs(),
t_existing_jobs(),
@@ -1212,6 +1218,32 @@ t_jobs_churn_even_if_not_all_max_jobs_are_running() ->
end).
+t_jobs_dont_churn_if_there_are_available_running_slots() ->
+ ?_test(begin
+ setup_jobs([
+ continuous_running(1),
+ continuous_running(2)
+ ]),
+ reschedule(mock_state(2, 2)),
+ ?assertEqual({2, 0}, run_stop_count()),
+ ?assertEqual([], jobs_stopped()),
+ ?assertEqual(0, meck:num_calls(couch_replicator_scheduler_sup, start_child, 1))
+ end).
+
+
+t_start_only_pending_jobs_do_not_churn_existing_ones() ->
+ ?_test(begin
+ setup_jobs([
+ continuous(1),
+ continuous_running(2)
+ ]),
+ reschedule(mock_state(2, 2)),
+ ?assertEqual(1, meck:num_calls(couch_replicator_scheduler_sup, start_child, 1)),
+ ?assertEqual([], jobs_stopped()),
+ ?assertEqual({2, 0}, run_stop_count())
+ end).
+
+
t_dont_stop_if_nothing_pending() ->
?_test(begin
setup_jobs([continuous_running(1), continuous_running(2)]),