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

rnewson pushed a commit to branch auto-delete-tseq
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4c4c11a304418f5f2b331bbb71b2554b7d207bfc
Author: Robert Newson <rnew...@apache.org>
AuthorDate: Tue Sep 16 15:25:01 2025 +0100

    add get/set interface for auto purge properties
---
 src/chttpd/src/chttpd_db.erl             | 20 ++++++-
 src/chttpd/src/chttpd_httpd_handlers.erl |  1 +
 src/fabric/src/fabric.erl                | 10 +++-
 src/fabric/src/fabric_auto_purge.erl     | 96 ++++++++++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 4bab083d4..61d5f06ea 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -30,7 +30,8 @@
     handle_view_cleanup_req/2,
     update_doc/4,
     http_code_from_status/1,
-    handle_partition_req/2
+    handle_partition_req/2,
+    handle_auto_purge_req/2
 ]).
 
 -import(
@@ -390,6 +391,23 @@ update_partition_stats(PathParts) ->
             ok
     end.
 
+handle_auto_purge_req(#httpd{method = 'GET'} = Req, Db) ->
+    case fabric:get_auto_purge_props(Db) of
+        {ok, AutoPurgeProps} ->
+            send_json(Req, {AutoPurgeProps});
+        {error, Reason} ->
+            chttpd:send_error(Req, Reason)
+    end;
+handle_auto_purge_req(#httpd{method = 'POST'} = Req, Db) ->
+    chttpd:validate_ctype(Req, "application/json"),
+    {AutoPurgeProps} = chttpd:json_body_obj(Req),
+    case fabric:set_auto_purge_props(Db, AutoPurgeProps) of
+        ok ->
+            send_json(Req, 202, {[{ok, true}]});
+        {error, Reason} ->
+            chttpd:send_error(Req, Reason)
+    end.
+
 handle_design_req(
     #httpd{
         path_parts = [_DbName, _Design, Name, <<"_", _/binary>> = Action | 
_Rest]
diff --git a/src/chttpd/src/chttpd_httpd_handlers.erl 
b/src/chttpd/src/chttpd_httpd_handlers.erl
index 932b52e5f..3e499b72d 100644
--- a/src/chttpd/src/chttpd_httpd_handlers.erl
+++ b/src/chttpd/src/chttpd_httpd_handlers.erl
@@ -35,6 +35,7 @@ db_handler(<<"_design">>) -> fun 
chttpd_db:handle_design_req/2;
 db_handler(<<"_partition">>) -> fun chttpd_db:handle_partition_req/2;
 db_handler(<<"_temp_view">>) -> fun chttpd_view:handle_temp_view_req/2;
 db_handler(<<"_changes">>) -> fun chttpd_db:handle_changes_req/2;
+db_handler(<<"_auto_purge">>) -> fun chttpd_db:handle_auto_purge_req/2;
 db_handler(_) -> no_match.
 
 design_handler(<<"_view">>) -> fun chttpd_view:handle_view_req/3;
diff --git a/src/fabric/src/fabric.erl b/src/fabric/src/fabric.erl
index a2bf82482..c83b98f39 100644
--- a/src/fabric/src/fabric.erl
+++ b/src/fabric/src/fabric.erl
@@ -35,7 +35,9 @@
     set_purge_infos_limit/3,
     get_purged_infos/1,
     compact/1, compact/2,
-    get_partition_info/2
+    get_partition_info/2,
+    get_auto_purge_props/1,
+    set_auto_purge_props/2
 ]).
 
 % Documents
@@ -132,6 +134,12 @@ get_db_info(DbName) ->
 get_partition_info(DbName, Partition) ->
     fabric_db_partition_info:go(dbname(DbName), Partition).
 
+get_auto_purge_props(DbName) ->
+    fabric_auto_purge:get(dbname(DbName)).
+
+set_auto_purge_props(DbName, AutoPurgeProps) ->
+    fabric_auto_purge:set(dbname(DbName), AutoPurgeProps).
+
 %% @doc the number of docs in a database
 %% @equiv get_doc_count(DbName, <<"_all_docs">>)
 get_doc_count(DbName) ->
diff --git a/src/fabric/src/fabric_auto_purge.erl 
b/src/fabric/src/fabric_auto_purge.erl
new file mode 100644
index 000000000..a84947f9d
--- /dev/null
+++ b/src/fabric/src/fabric_auto_purge.erl
@@ -0,0 +1,96 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(fabric_auto_purge).
+
+-export([get/1, set/2]).
+
+-export([set_int/2]).
+
+-include_lib("couch/include/couch_db.hrl").
+-define(KEY, <<"auto_purge">>).
+
+get(DbName) when is_binary(DbName) ->
+    with_db(fun(Db) -> get_cb(Db, DbName) end).
+
+get_cb(Db, DocId) ->
+    case couch_db:open_doc(Db, DocId) of
+        {error, Reason} ->
+            {error, Reason};
+        {not_found, _Reason} ->
+            {ok, []};
+        {ok, Doc} ->
+            {Props} = couch_doc:to_json_obj(Doc, []),
+            {AutoPurgeProps} = couch_util:get_value(?KEY, Props, {[]}),
+            {ok, AutoPurgeProps}
+    end.
+
+set(DbName, AutoPurgeProps) when is_binary(DbName) ->
+    Node = hd(mem3_util:live_nodes()),
+    case rpc:call(Node, ?MODULE, set_int, [DbName, AutoPurgeProps]) of
+        {badrpc, Reason} ->
+            {error, Reason};
+        Result ->
+            Result
+    end.
+
+set_int(DbName, AutoPurgeProps) ->
+    case validate_props(AutoPurgeProps) of
+        {error, Reason} ->
+            {error, Reason};
+        ok ->
+            with_db(fun(Db) -> set_cb(Db, DbName, AutoPurgeProps) end)
+    end.
+
+set_cb(Db, DocId, AutoPurgeProps) ->
+    case couch_db:open_doc(Db, DocId) of
+        {error, Reason} ->
+            {error, Reason};
+        {not_found, _Reason} ->
+            {error, not_found};
+        {ok, #doc{} = Doc0} ->
+            {Props0} = couch_doc:to_json_obj(Doc0, []),
+            Props1 = lists:keystore(?KEY, 1, Props0, {?KEY, {AutoPurgeProps}}),
+            Doc1 = couch_doc:from_json_obj({Props1}),
+            case couch_db:update_doc(Db, Doc1, []) of
+                {ok, _NewRev} ->
+                    ok;
+                {error, Reason} ->
+                    {error, Reason}
+            end
+    end.
+
+validate_props([]) ->
+    ok;
+validate_props([{<<"deleted_document_ttl">>, Value} | Rest]) when 
is_integer(Value) ->
+    validate_props(Rest);
+validate_props([{<<"deleted_document_ttl">>, _Value} | _Rest]) ->
+    {error, <<"deleted_document_ttl must be an integer">>};
+validate_props([{_K, _V} | _Rest]) ->
+    {error, <<"invalid auto purge property">>};
+validate_props(_Else) ->
+    {error, <<"malformed auto purge body">>}.
+
+with_db(Fun) ->
+    case couch_db:open_int(dbs_db(), [?ADMIN_CTX]) of
+        {ok, Db} ->
+            try
+                Fun(Db)
+            after
+                catch couch_db:close(Db)
+            end;
+        Else ->
+            Else
+    end.
+
+dbs_db() ->
+    ?l2b(config:get("mem3", "shards_db", "_dbs")).

Reply via email to