You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2025/01/15 22:40:20 UTC

(couchdb) branch remove-idle-check-timeout created (now f7ba47d57)

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

vatamane pushed a change to branch remove-idle-check-timeout
in repository https://gitbox.apache.org/repos/asf/couchdb.git


      at f7ba47d57 Remove idle check timeout

This branch includes the following new commits:

     new f7ba47d57 Remove idle check timeout

The 1 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.



(couchdb) 01/01: Remove idle check timeout

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

vatamane pushed a commit to branch remove-idle-check-timeout
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit f7ba47d57cc10453c4a221629fd977f43b140efe
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Wed Jan 15 17:35:51 2025 -0500

    Remove idle check timeout
    
    7 years ago we added an idle-check timeout to force idle system shard to close
    [1]. It seemed like a relevant setting for Cloudant were at the time we had a
    large number of open `_replicator` dbs per server. However, at Cloudant we only
    enabled it once, it failed as it closed too many shards too quickly and then
    they had to be re-open then soon enough, which added extra load, we disabled
    ran with `infinity` ever since.
    
    We never documented it anywhere so let's remove it.
---
 src/couch/src/couch_bt_engine.erl         |  5 --
 src/couch/src/couch_db_engine.erl         | 14 -----
 src/couch/src/couch_db_updater.erl        | 91 +++++++------------------------
 src/couch/src/couch_file.erl              | 10 ----
 src/couch/test/eunit/couch_file_tests.erl | 10 ----
 5 files changed, 20 insertions(+), 110 deletions(-)

diff --git a/src/couch/src/couch_bt_engine.erl b/src/couch/src/couch_bt_engine.erl
index 7bc02146e..1cd3f6d00 100644
--- a/src/couch/src/couch_bt_engine.erl
+++ b/src/couch/src/couch_bt_engine.erl
@@ -30,8 +30,6 @@
     decref/1,
     monitored_by/1,
 
-    last_activity/1,
-
     get_compacted_seq/1,
     get_del_doc_count/1,
     get_disk_version/1,
@@ -212,9 +210,6 @@ monitored_by(St) ->
             []
     end.
 
-last_activity(#st{fd = Fd}) ->
-    couch_file:last_read(Fd).
-
 get_compacted_seq(#st{header = Header}) ->
     couch_bt_engine_header:get(Header, compacted_seq).
 
diff --git a/src/couch/src/couch_db_engine.erl b/src/couch/src/couch_db_engine.erl
index 052a527e3..54f2c1482 100644
--- a/src/couch/src/couch_db_engine.erl
+++ b/src/couch/src/couch_db_engine.erl
@@ -180,14 +180,6 @@
 -callback decref(DbHandle :: db_handle()) -> ok.
 -callback monitored_by(DbHande :: db_handle()) -> [pid()].
 
-% This is called in the context of couch_db_updater:handle_info/2
-% and should return the timestamp of the last activity of
-% the database. If a storage has no notion of activity or the
-% value would be hard to report its ok to just return the
-% result of os:timestamp/0 as this will just disable idle
-% databases from automatically closing.
--callback last_activity(DbHandle :: db_handle()) -> erlang:timestamp().
-
 % All of the get_* functions may be called from many
 % processes concurrently.
 
@@ -673,8 +665,6 @@
     decref/1,
     monitored_by/1,
 
-    last_activity/1,
-
     get_engine/1,
     get_compacted_seq/1,
     get_del_doc_count/1,
@@ -791,10 +781,6 @@ monitored_by(#db{} = Db) ->
     #db{engine = {Engine, EngineState}} = Db,
     Engine:monitored_by(EngineState).
 
-last_activity(#db{} = Db) ->
-    #db{engine = {Engine, EngineState}} = Db,
-    Engine:last_activity(EngineState).
-
 get_engine(#db{} = Db) ->
     #db{engine = {Engine, _}} = Db,
     Engine.
diff --git a/src/couch/src/couch_db_updater.erl b/src/couch/src/couch_db_updater.erl
index d1b4c1d2d..3f6c8886d 100644
--- a/src/couch/src/couch_db_updater.erl
+++ b/src/couch/src/couch_db_updater.erl
@@ -19,7 +19,6 @@
 -include_lib("couch/include/couch_db.hrl").
 -include("couch_db_int.hrl").
 
--define(IDLE_LIMIT_DEFAULT, 61000).
 % 10 GiB
 -define(DEFAULT_MAX_PARTITION_SIZE, 16#280000000).
 
@@ -34,7 +33,6 @@
 
 init({Engine, DbName, FilePath, Options0}) ->
     erlang:put(io_priority, {db_update, DbName}),
-    update_idle_limit_from_config(),
     DefaultSecObj = default_security_object(DbName),
     Options = [{default_security_object, DefaultSecObj} | Options0],
     try
@@ -51,7 +49,7 @@ init({Engine, DbName, FilePath, Options0}) ->
         % couch_db:validate_doc_update, which loads them lazily.
         NewDb = Db#db{main_pid = self()},
         proc_lib:init_ack({ok, NewDb}),
-        gen_server:enter_loop(?MODULE, [], NewDb, idle_limit())
+        gen_server:enter_loop(?MODULE, [], NewDb)
     catch
         throw:InitError ->
             proc_lib:init_ack(InitError)
@@ -63,39 +61,39 @@ terminate(Reason, Db) ->
     ok.
 
 handle_call(get_db, _From, Db) ->
-    {reply, {ok, Db}, Db, idle_limit()};
+    {reply, {ok, Db}, Db};
 handle_call(start_compact, _From, Db) ->
-    {noreply, NewDb, _Timeout} = handle_cast(start_compact, Db),
-    {reply, {ok, NewDb#db.compactor_pid}, NewDb, idle_limit()};
+    {noreply, NewDb} = handle_cast(start_compact, Db),
+    {reply, {ok, NewDb#db.compactor_pid}, NewDb};
 handle_call(compactor_pid, _From, #db{compactor_pid = Pid} = Db) ->
-    {reply, Pid, Db, idle_limit()};
+    {reply, Pid, Db};
 handle_call(cancel_compact, _From, #db{compactor_pid = nil} = Db) ->
-    {reply, ok, Db, idle_limit()};
+    {reply, ok, Db};
 handle_call(cancel_compact, _From, #db{compactor_pid = Pid} = Db) ->
     unlink(Pid),
     exit(Pid, kill),
     couch_server:delete_compaction_files(Db#db.name),
     Db2 = Db#db{compactor_pid = nil},
     ok = couch_server:db_updated(Db2),
-    {reply, ok, Db2, idle_limit()};
+    {reply, ok, Db2};
 handle_call({set_security, NewSec}, _From, #db{} = Db) ->
     {ok, NewDb} = couch_db_engine:set_security(Db, NewSec),
     NewSecDb = commit_data(NewDb#db{
         security = NewSec
     }),
     ok = couch_server:db_updated(NewSecDb),
-    {reply, ok, NewSecDb, idle_limit()};
+    {reply, ok, NewSecDb};
 handle_call({set_revs_limit, Limit}, _From, Db) ->
     {ok, Db2} = couch_db_engine:set_revs_limit(Db, Limit),
     Db3 = commit_data(Db2),
     ok = couch_server:db_updated(Db3),
-    {reply, ok, Db3, idle_limit()};
+    {reply, ok, Db3};
 handle_call({set_purge_infos_limit, Limit}, _From, Db) ->
     {ok, Db2} = couch_db_engine:set_purge_infos_limit(Db, Limit),
     ok = couch_server:db_updated(Db2),
-    {reply, ok, Db2, idle_limit()};
+    {reply, ok, Db2};
 handle_call({purge_docs, [], _}, _From, Db) ->
-    {reply, {ok, []}, Db, idle_limit()};
+    {reply, {ok, []}, Db};
 handle_call({purge_docs, PurgeReqs0, Options}, _From, Db) ->
     % Filter out any previously applied updates during
     % internal replication
@@ -116,11 +114,11 @@ handle_call({purge_docs, PurgeReqs0, Options}, _From, Db) ->
                 )
         end,
     {ok, NewDb, Replies} = purge_docs(Db, PurgeReqs),
-    {reply, {ok, Replies}, NewDb, idle_limit()};
+    {reply, {ok, Replies}, NewDb};
 handle_call(Msg, From, Db) ->
     case couch_db_engine:handle_db_updater_call(Msg, From, Db) of
         {reply, Resp, NewDb} ->
-            {reply, Resp, NewDb, idle_limit()};
+            {reply, Resp, NewDb};
         Else ->
             Else
     end.
@@ -128,7 +126,7 @@ handle_call(Msg, From, Db) ->
 handle_cast({load_validation_funs, ValidationFuns}, Db) ->
     Db2 = Db#db{validate_doc_funs = ValidationFuns},
     ok = couch_server:db_updated(Db2),
-    {noreply, Db2, idle_limit()};
+    {noreply, Db2};
 handle_cast(start_compact, Db) ->
     case Db#db.compactor_pid of
         nil ->
@@ -146,16 +144,14 @@ handle_cast(start_compact, Db) ->
             couch_log:Level("Starting compaction for db \"~s\" at ~p", Args),
             {ok, Db2} = couch_db_engine:start_compaction(Db),
             ok = couch_server:db_updated(Db2),
-            {noreply, Db2, idle_limit()};
+            {noreply, Db2};
         _ ->
             % compact currently running, this is a no-op
-            {noreply, Db, idle_limit()}
+            {noreply, Db}
     end;
 handle_cast({compact_done, _Engine, CompactInfo}, #db{} = OldDb) ->
     {ok, NewDb} = couch_db_engine:finish_compaction(OldDb, CompactInfo),
     {noreply, NewDb};
-handle_cast(wakeup, Db) ->
-    {noreply, Db, idle_limit()};
 handle_cast(Msg, #db{name = Name} = Db) ->
     couch_log:error(
         "Database `~s` updater received unexpected cast: ~p",
@@ -213,40 +209,20 @@ handle_info(
                     false ->
                         Db2
                 end,
-            {noreply, Db3, hibernate_if_no_idle_limit()}
+            {noreply, Db3, hibernate}
     catch
         throw:retry ->
             [catch (ClientPid ! {retry, self()}) || ClientPid <- Clients],
-            {noreply, Db, hibernate_if_no_idle_limit()}
+            {noreply, Db, hibernate}
     end;
 handle_info({'EXIT', _Pid, normal}, Db) ->
-    {noreply, Db, idle_limit()};
+    {noreply, Db};
 handle_info({'EXIT', _Pid, Reason}, Db) ->
     {stop, Reason, Db};
-handle_info(timeout, #db{name = DbName} = Db) ->
-    IdleLimitMSec = update_idle_limit_from_config(),
-    case couch_db:is_idle(Db) of
-        true ->
-            LastActivity = couch_db_engine:last_activity(Db),
-            DtMSec = timer:now_diff(os:timestamp(), LastActivity) div 1000,
-            MSecSinceLastActivity = max(0, DtMSec),
-            case MSecSinceLastActivity > IdleLimitMSec of
-                true ->
-                    ok = couch_server:close_db_if_idle(DbName);
-                false ->
-                    ok
-            end;
-        false ->
-            ok
-    end,
-    % Send a message to wake up and then hibernate. Hibernation here is done to
-    % force a thorough garbage collection.
-    gen_server:cast(self(), wakeup),
-    {noreply, Db, hibernate};
 handle_info(Msg, Db) ->
     case couch_db_engine:handle_db_updater_info(Msg, Db) of
         {noreply, NewDb} ->
-            {noreply, NewDb, idle_limit()};
+            {noreply, NewDb};
         Else ->
             Else
     end.
@@ -942,33 +918,6 @@ default_security_object(_DbName) ->
             []
     end.
 
-% These functions rely on using the process dictionary. This is
-% usually frowned upon however in this case it is done to avoid
-% changing to a different server state record. Once PSE (Pluggable
-% Storage Engine) code lands this should be moved to the #db{} record.
-update_idle_limit_from_config() ->
-    Default = integer_to_list(?IDLE_LIMIT_DEFAULT),
-    IdleLimit =
-        case config:get("couchdb", "idle_check_timeout", Default) of
-            "infinity" ->
-                infinity;
-            Milliseconds ->
-                list_to_integer(Milliseconds)
-        end,
-    put(idle_limit, IdleLimit),
-    IdleLimit.
-
-idle_limit() ->
-    get(idle_limit).
-
-hibernate_if_no_idle_limit() ->
-    case idle_limit() of
-        infinity ->
-            hibernate;
-        Timeout when is_integer(Timeout) ->
-            Timeout
-    end.
-
 -ifdef(TEST).
 -include_lib("eunit/include/eunit.hrl").
 
diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl
index 8c7370688..46f80f949 100644
--- a/src/couch/src/couch_file.erl
+++ b/src/couch/src/couch_file.erl
@@ -45,7 +45,6 @@
 -export([append_terms/2, append_terms/3]).
 -export([write_header/2, read_header/1]).
 -export([delete/2, delete/3, nuke_dir/2, init_delete_dir/1]).
--export([last_read/1]).
 
 % gen_server callbacks
 -export([init/1, terminate/2, format_status/2]).
@@ -404,16 +403,11 @@ init_status_error(ReturnPid, Ref, Error) ->
     ReturnPid ! {Ref, self(), Error},
     ignore.
 
-last_read(Fd) when is_pid(Fd) ->
-    Now = os:timestamp(),
-    couch_util:process_dict_get(Fd, read_timestamp, Now).
-
 % server functions
 
 init({Filepath, Options, ReturnPid, Ref}) ->
     OpenOptions = file_open_options(Options),
     IsSys = lists:member(sys_db, Options),
-    update_read_timestamp(),
     case lists:member(create, Options) of
         true ->
             filelib:ensure_dir(Filepath),
@@ -493,7 +487,6 @@ terminate(_Reason, #file{fd = Fd}) ->
 handle_call(close, _From, #file{fd = Fd} = File) ->
     {stop, normal, file:close(Fd), File#file{fd = nil}};
 handle_call({pread_iolists, PosL}, _From, File) ->
-    update_read_timestamp(),
     LocNums1 = [{Pos, 4} || Pos <- PosL],
     DataSizes = read_multi_raw_iolists_int(File, LocNums1),
     MapFun = fun({LenIoList, NextPos}) ->
@@ -872,9 +865,6 @@ is_idle(#file{is_sys = false}) ->
 process_info(Pid) ->
     couch_util:process_dict_get(Pid, couch_file_fd).
 
-update_read_timestamp() ->
-    put(read_timestamp, os:timestamp()).
-
 %% in event of a partially successful write.
 reset_eof(#file{} = File) ->
     {ok, Eof} = file:position(File#file.fd, eof),
diff --git a/src/couch/test/eunit/couch_file_tests.erl b/src/couch/test/eunit/couch_file_tests.erl
index 78db4eb9b..ec024e4bb 100644
--- a/src/couch/test/eunit/couch_file_tests.erl
+++ b/src/couch/test/eunit/couch_file_tests.erl
@@ -95,7 +95,6 @@ read_write_test_() ->
                     ?TDEF_FE(should_catch_pread_failure),
                     ?TDEF_FE(should_truncate),
                     ?TDEF_FE(should_set_db_pid),
-                    ?TDEF_FE(should_update_last_read_time),
                     ?TDEF_FE(should_open_read_only),
                     ?TDEF_FE(should_apply_overwrite_create_option),
                     ?TDEF_FE(should_error_on_creation_if_exists),
@@ -245,15 +244,6 @@ should_set_db_pid(Fd) ->
     ),
     ?assertNot(is_process_alive(Fd)).
 
-should_update_last_read_time(Fd) ->
-    {ok, Pos, _} = couch_file:append_term(Fd, foo),
-    ReadTs1 = couch_file:last_read(Fd),
-    ?assertMatch({_, _, _}, ReadTs1),
-    {ok, foo} = couch_file:pread_term(Fd, Pos),
-    ReadTs2 = couch_file:last_read(Fd),
-    ?assertMatch({_, _, _}, ReadTs2),
-    ?assert(ReadTs2 > ReadTs1).
-
 should_open_read_only(Fd) ->
     {_, Path} = couch_file:process_info(Fd),
     {ok, Pos, _} = couch_file:append_term(Fd, foo),