diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2019-10-22 14:27:13 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2019-10-22 17:23:15 -0400 |
commit | 79cfc1df5e5e8e0d495bc58187306e8f7bfe06dc (patch) | |
tree | e408ca88f092681eb594057dbe1b3e85acafbbbd | |
parent | ae29ffcd799b7db85f715b0106941143a4ba04aa (diff) | |
download | couchdb-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.erl | 36 |
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)]), |