summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-10-22 14:27:13 -0400
committerNick Vatamaniuc <nickva@users.noreply.github.com>2019-10-22 17:23:15 -0400
commit79cfc1df5e5e8e0d495bc58187306e8f7bfe06dc (patch)
treee408ca88f092681eb594057dbe1b3e85acafbbbd
parentae29ffcd799b7db85f715b0106941143a4ba04aa (diff)
downloadcouchdb-79cfc1df5e5e8e0d495bc58187306e8f7bfe06dc.tar.gz
Avoid churning replication jobs if there is enough room to run pending jobs
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)]),