diff options
author | Adam Kocoloski <kocolosk@apache.org> | 2019-09-06 12:10:01 -0400 |
---|---|---|
committer | Adam Kocoloski <kocolosk@apache.org> | 2019-09-24 14:43:04 -0400 |
commit | dddaa3cd44b65d90bc9bd73888c19c0f703b7c97 (patch) | |
tree | be34c959890250bd524d2e7e7eb7c1486eece5e9 | |
parent | 8553ee662c6bfd08daabf521cf5c46e0e1696b9b (diff) | |
download | couchdb-dddaa3cd44b65d90bc9bd73888c19c0f703b7c97.tar.gz |
Support scheduling compactions during time windows
This patch allows administrators to configure smoosh to only
execute compactions during a specified time window on a
per-channel basis. The (partial) configuration looks like
[smoosh]
db_channels=overnight_channel
[smoosh.overnight_channel]
from = 22:00
to = 06:00
strict_window = true
If `strict_window` is set to true, smoosh will suspend all
currently running compactions in this channel when leaving the
time window, and resume them in the next window. If left at the
default, currently running compactions will be allowed to complete
but no new compactions will be started until the window is open again.
-rw-r--r-- | src/smoosh_channel.erl | 27 | ||||
-rw-r--r-- | src/smoosh_utils.erl | 34 |
2 files changed, 61 insertions, 0 deletions
diff --git a/src/smoosh_channel.erl b/src/smoosh_channel.erl index 58d3ce73a..d8a8d14a9 100644 --- a/src/smoosh_channel.erl +++ b/src/smoosh_channel.erl @@ -63,6 +63,7 @@ flush(ServerRef) -> init(Name) -> schedule_unpause(), + erlang:send_after(60 * 1000, self(), check_window), {ok, #state{name=Name}}. handle_call({last_updated, Object}, _From, State0) -> @@ -151,6 +152,32 @@ handle_info({Ref, {ok, Pid}}, State0) when is_reference(Ref) -> {noreply, State} end; +handle_info(check_window, State0) -> + {ok, State} = code_change(nil, State0, nil), + #state{paused = Paused, name = Name} = State, + StrictWindow = smoosh_utils:get(Name, "strict_window", "false"), + FinalState = case {not Paused, smoosh_utils:in_allowed_window(Name)} of + {false, false} -> + % already in desired state + State; + {true, true} -> + % already in desired state + State; + {false, true} -> + % resume is always safe even if we did not previously suspend + {reply, ok, NewState} = handle_call(resume, nil, State), + NewState; + {true, false} -> + if StrictWindow =:= "true" -> + {reply, ok, NewState} = handle_call(suspend, nil, State), + NewState; + true -> + State#state{paused=true} + end + end, + erlang:send_after(60 * 1000, self(), check_window), + {noreply, FinalState}; + handle_info(pause, State0) -> {ok, State} = code_change(nil, State0, nil), {noreply, State#state{paused=true}}; diff --git a/src/smoosh_utils.erl b/src/smoosh_utils.erl index 78ef83aed..b433de033 100644 --- a/src/smoosh_utils.erl +++ b/src/smoosh_utils.erl @@ -14,6 +14,9 @@ -include_lib("couch/include/couch_db.hrl"). -export([get/2, get/3, group_pid/1, split/1, stringify/1, ignore_db/1]). +-export([ + in_allowed_window/1 +]). group_pid({Shard, GroupId}) -> case couch_view_group:open_db_group(Shard, GroupId) of @@ -56,3 +59,34 @@ ignore_db(DbName) when is_list(DbName) -> end; ignore_db(Db) -> ignore_db(couch_db:name(Db)). + +in_allowed_window(Channel) -> + From = parse_time(get(Channel, "from"), {00, 00}), + To = parse_time(get(Channel, "to"), {24, 00}), + in_allowed_window(From, To). + +in_allowed_window(From, To) -> + {HH, MM, _} = erlang:time(), + case From < To of + true -> + ({HH, MM} >= From) andalso ({HH, MM} < To); + false -> + ({HH, MM} >= From) orelse ({HH, MM} < To) + end. + + +parse_time(undefined, Default) -> + Default; +parse_time(String, Default) -> + case string:tokens(String, ":") of + [HH, MM] -> + try + {list_to_integer(HH), list_to_integer(MM)} + catch error:badarg -> + couch_log:error("Malformed compaction schedule configuration: ~s", [String]), + Default + end; + _Else -> + couch_log:error("Malformed compaction schedule configuration: ~s", [String]), + Default + end. |