This is an automated email from the ASF dual-hosted git repository. vatamane pushed a commit to branch accept-infinity-for-auto-purge-conifg in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 3db79febb09882a94a722359ca21a6574d55e413 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Wed Feb 25 02:23:13 2026 -0500 Allow infinity for auto purge ttl setting The explicit `infinity` value can work better with multiple config levels. Also, users can now enable ttl for the whole cluster but disable it for specific dbs by setting their ttl in {db}/_auto_purge to `infinity`. While at it, update the etc default.ini config comment since we switched to using the `{num}_{timeunit}` format. --- rel/overlay/etc/default.ini | 8 +++-- src/chttpd/src/chttpd_db.erl | 4 +++ src/couch/src/couch_auto_purge_plugin.erl | 21 +++++++++--- .../test/eunit/couch_auto_purge_plugin_tests.erl | 38 ++++++++++++++++++++++ src/docs/src/config/scanner.rst | 9 +++-- 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini index 6fbc99f58..462233d47 100644 --- a/rel/overlay/etc/default.ini +++ b/rel/overlay/etc/default.ini @@ -1224,9 +1224,11 @@ url = {{nouveau_url}} ; one request. ;max_batch_size = 500 -; The default time-to-live, measured in seconds, before a -; deleted document is eligible to be purged by the plugin. -; Defaults to undefined, which disables auto purging. +; The default time-to-live before a deleted document is eligible to be purged +; by the plugin. Possible formats are: {num}_{timeunit} (ex: 1000_sec, 30_min, +; 8_hours, 24_hours, 2_days, 3_weeks, 1_month, 2_years). Defaults to undefined +; (or "infinity") which disables auto purging. Individual database ttl settings +; will override this value. ;deleted_document_ttl = ; Set the log level for starting, stopping and purge report summary log entries. diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl index 5ef69f33f..200e705d2 100644 --- a/src/chttpd/src/chttpd_db.erl +++ b/src/chttpd/src/chttpd_db.erl @@ -412,6 +412,10 @@ handle_auto_purge_req(#httpd{} = Req, _Db) -> validate_auto_purge_props([]) -> ok; +validate_auto_purge_props([{<<"deleted_document_ttl">>, <<"infinity">>} | Rest]) -> + % Setting the value to "infinity" is way to explicilty disable auto-purge + % individual databases while allowing cluster level auto-purge to happen + validate_auto_purge_props(Rest); validate_auto_purge_props([{<<"deleted_document_ttl">>, Value} | Rest]) when is_binary(Value) -> case couch_scanner_util:parse_non_weekday_period(?b2l(Value)) of undefined -> diff --git a/src/couch/src/couch_auto_purge_plugin.erl b/src/couch/src/couch_auto_purge_plugin.erl index 4fd904fdd..5589be244 100644 --- a/src/couch/src/couch_auto_purge_plugin.erl +++ b/src/couch/src/couch_auto_purge_plugin.erl @@ -197,6 +197,8 @@ ttl(St, DbName) -> case parse_deleted_document_ttl(AutoPurgeProps) of TTL when is_integer(TTL) -> TTL; + infinity -> + infinity; undefined -> undefined; Else -> @@ -215,22 +217,33 @@ ttl(St, DbName) -> ), undefined end, - if - DbTTL /= undefined -> DbTTL; - DefaultTTL /= undefined -> parse_ttl(DefaultTTL); - true -> undefined + case {DbTTL, DefaultTTL} of + {undefined, undefined} -> + undefined; + {undefined, infinity} -> + undefined; + {infinity, _} -> + undefined; + {undefined, Val} when is_list(Val) -> + parse_ttl(Val); + {Val, _} when is_integer(Val) -> + Val end. parse_deleted_document_ttl(AutoPurgeProps) -> case couch_util:get_value(<<"deleted_document_ttl">>, AutoPurgeProps) of undefined -> undefined; + <<"infinity">> -> + infinity; Else -> parse_ttl(Else) end. parse_ttl(Bin) when is_binary(Bin) -> parse_ttl(binary_to_list(Bin)); +parse_ttl("infinity") -> + infinity; parse_ttl([$- | TTL]) -> -(parse_ttl(TTL)); parse_ttl(TTL) -> diff --git a/src/couch/test/eunit/couch_auto_purge_plugin_tests.erl b/src/couch/test/eunit/couch_auto_purge_plugin_tests.erl index 38b325022..8e71be0a1 100644 --- a/src/couch/test/eunit/couch_auto_purge_plugin_tests.erl +++ b/src/couch/test/eunit/couch_auto_purge_plugin_tests.erl @@ -26,6 +26,9 @@ couch_quickjs_scanner_plugin_test_() -> ?TDEF_FE(t_no_auto_purge_by_default, 10), ?TDEF_FE(t_auto_purge_after_config_ttl, 10), ?TDEF_FE(t_auto_purge_after_db_ttl, 10), + ?TDEF_FE(t_no_auto_purge_after_db_ttl_set_to_infinity, 10), + ?TDEF_FE(t_no_auto_purge_after_config_ttl_set_to_infinity, 10), + ?TDEF_FE(t_db_auto_purge_overrides_cluster_ttl_infinity, 10), ?TDEF_FE(t_min_batch_size_1, 10), ?TDEF_FE(t_min_batch_size_2, 10), ?TDEF_FE(t_max_batch_size_1, 10), @@ -90,6 +93,41 @@ t_auto_purge_after_db_ttl({_, DbName}) -> ?assertEqual(0, doc_del_count(DbName)), ok. +t_no_auto_purge_after_config_ttl_set_to_infinity({_, DbName}) -> + config:set(atom_to_list(?PLUGIN), "deleted_document_ttl", "infinity", false), + ok = add_doc(DbName, <<"doc1">>, #{<<"_deleted">> => true}), + ?assertEqual(1, doc_del_count(DbName)), + meck:reset(couch_scanner_server), + meck:reset(?PLUGIN), + config:set("couch_scanner_plugins", atom_to_list(?PLUGIN), "true", false), + wait_exit(10000), + ?assertEqual(1, doc_del_count(DbName)), + ok. + +t_no_auto_purge_after_db_ttl_set_to_infinity({_, DbName}) -> + config:set(atom_to_list(?PLUGIN), "deleted_document_ttl", "-3_hour", false), + ok = fabric:set_auto_purge_props(DbName, [{<<"deleted_document_ttl">>, <<"infinity">>}]), + ok = add_doc(DbName, <<"doc1">>, #{<<"_deleted">> => true}), + ?assertEqual(1, doc_del_count(DbName)), + meck:reset(couch_scanner_server), + meck:reset(?PLUGIN), + config:set("couch_scanner_plugins", atom_to_list(?PLUGIN), "true", false), + wait_exit(10000), + ?assertEqual(1, doc_del_count(DbName)), + ok. + +t_db_auto_purge_overrides_cluster_ttl_infinity({_, DbName}) -> + config:set(atom_to_list(?PLUGIN), "deleted_document_ttl", "infinity", false), + ok = fabric:set_auto_purge_props(DbName, [{<<"deleted_document_ttl">>, "-3_hour"}]), + ok = add_doc(DbName, <<"doc1">>, #{<<"_deleted">> => true}), + ?assertEqual(1, doc_del_count(DbName)), + meck:reset(couch_scanner_server), + meck:reset(?PLUGIN), + config:set("couch_scanner_plugins", atom_to_list(?PLUGIN), "true", false), + wait_exit(10000), + ?assertEqual(0, doc_del_count(DbName)), + ok. + t_dry_run({_, DbName}) -> config:set(atom_to_list(?PLUGIN), "dry_run", "true", false), config:set(atom_to_list(?PLUGIN), "deleted_document_ttl", "-3_hour", false), diff --git a/src/docs/src/config/scanner.rst b/src/docs/src/config/scanner.rst index e03ad7006..cb49acd6f 100644 --- a/src/docs/src/config/scanner.rst +++ b/src/docs/src/config/scanner.rst @@ -259,10 +259,13 @@ settings in their ``[{plugin}]`` section. Set the default interval before the plugin will purge a deleted document. Possible ttl formats are: ``{num}_{timeunit}`` (ex.: ``1000_sec``, ``30_min``, ``8_hours``, ``24_hour``, ``2_days``, - ``3_weeks``, ``1_month``). + ``3_weeks``, ``1_month``) or ``infinity``. + The database may override this setting with the - :ref:`api/db/auto_purge` endpoint. If neither is set, the - plugin will not purge deleted documents. + :ref:`api/db/auto_purge` endpoint. If neither is set, the plugin will + not purge deleted documents. Setting the config value to ``infinity`` + disables cluster level auto-purge, which may be used to run auto-purge + only for specific databases with the database level settings. .. config:option:: log_level
