You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ko...@apache.org on 2019/09/11 15:51:23 UTC

[couchdb-smoosh] branch scheduled-smoosh updated (1e27fb2 -> 162db91)

This is an automated email from the ASF dual-hosted git repository.

kocolosk pushed a change to branch scheduled-smoosh
in repository https://gitbox.apache.org/repos/asf/couchdb-smoosh.git.


 discard 1e27fb2  Add unit tests for scheduling window logic
 discard c6c0742  Fix check_window responses
 discard 1cf2048  Support scheduling compactions during time windows
     new f2068ad  Support scheduling compactions during time windows
     new 162db91  Add unit tests for scheduling window logic

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (1e27fb2)
            \
             N -- N -- N   refs/heads/scheduled-smoosh (162db91)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:


[couchdb-smoosh] 02/02: Add unit tests for scheduling window logic

Posted by ko...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kocolosk pushed a commit to branch scheduled-smoosh
in repository https://gitbox.apache.org/repos/asf/couchdb-smoosh.git

commit 162db91b731d6e71e51a89495ddbd6bef2242451
Author: Adam Kocoloski <ko...@apache.org>
AuthorDate: Wed Sep 11 11:49:37 2019 -0400

    Add unit tests for scheduling window logic
---
 test/exunit/scheduling_window_test.exs | 81 ++++++++++++++++++++++++++++++++++
 test/exunit/test_helper.exs            |  2 +
 2 files changed, 83 insertions(+)

diff --git a/test/exunit/scheduling_window_test.exs b/test/exunit/scheduling_window_test.exs
new file mode 100644
index 0000000..7fa6c23
--- /dev/null
+++ b/test/exunit/scheduling_window_test.exs
@@ -0,0 +1,81 @@
+defmodule SmooshSchedulingWindowTest do
+  use Couch.Test.ExUnit.Case
+
+  alias Couch.Test.Setup
+
+  setup_all(context) do
+    test_ctx = :test_util.start_couch([])
+
+    on_exit(fn ->
+      :config.delete('smoosh.test_channel', 'from')
+      :config.delete('smoosh.test_channel', 'to')
+      :test_util.stop_couch(test_ctx)
+    end)
+
+    context
+  end
+
+  test "in_allowed_window returns true by default", _context do
+    assert :smoosh_utils.in_allowed_window('nonexistent_channel') == true
+  end
+
+  test "in_allowed_window ignores bad input", _context do
+    :config.set('smoosh.test_channel', 'from', 'midnight', false)
+    :config.set('smoosh.test_channel', 'to', 'infinity', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == true
+  end
+
+  test "in_allowed_window returns false when now < from < to", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, 18_000)
+    to = DateTime.add(now, 36_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == false
+  end
+
+  test "in_allowed_window returns true when from < now < to", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, -18_000)
+    to = DateTime.add(now, 18_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == true
+  end
+
+  test "in_allowed_window returns false when from < to < now", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, -36_000)
+    to = DateTime.add(now, -18_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == false
+  end
+
+  test "in_allowed_window returns true when to < from < now", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, -18_000)
+    to = DateTime.add(now, -36_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == true
+  end
+
+  test "in_allowed_window returns false when to < now < from", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, 18_000)
+    to = DateTime.add(now, -18_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == false
+  end
+
+  test "in_allowed_window returns true when now < to < from", _context do
+    now = DateTime.utc_now()
+    from = DateTime.add(now, 36_000)
+    to = DateTime.add(now, 18_000)
+    :config.set('smoosh.test_channel', 'from', '#{from.hour}:#{from.minute}', false)
+    :config.set('smoosh.test_channel', 'to', '#{to.hour}:#{to.minute}', false)
+    assert :smoosh_utils.in_allowed_window('test_channel') == true
+  end
+end
diff --git a/test/exunit/test_helper.exs b/test/exunit/test_helper.exs
new file mode 100644
index 0000000..3140500
--- /dev/null
+++ b/test/exunit/test_helper.exs
@@ -0,0 +1,2 @@
+ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
+ExUnit.start()


[couchdb-smoosh] 01/02: Support scheduling compactions during time windows

Posted by ko...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

kocolosk pushed a commit to branch scheduled-smoosh
in repository https://gitbox.apache.org/repos/asf/couchdb-smoosh.git

commit f2068adf4b04cd8b9d2d772f7d2911400c2cf84c
Author: Adam Kocoloski <ko...@apache.org>
AuthorDate: Fri Sep 6 12:10:01 2019 -0400

    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.
---
 src/smoosh_channel.erl | 27 +++++++++++++++++++++++++++
 src/smoosh_utils.erl   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/src/smoosh_channel.erl b/src/smoosh_channel.erl
index 58d3ce7..d8a8d14 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 78ef83a..b433de0 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.