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 1d31d05b92f95988779483cd5088881a2e5dd432
Author: Robert Newson <[email protected]>
AuthorDate: Tue Sep 2 15:32:21 2025 +0100

    wip
---
 src/couch/src/couch_tombstone_remover.erl | 90 +++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/src/couch/src/couch_tombstone_remover.erl 
b/src/couch/src/couch_tombstone_remover.erl
new file mode 100644
index 000000000..4a5304816
--- /dev/null
+++ b/src/couch/src/couch_tombstone_remover.erl
@@ -0,0 +1,90 @@
+% 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(couch_tombstone_remover).
+-behaviour(couch_scanner_plugin).
+
+-export([
+    start/2,
+    resume/2,
+    complete/1,
+    checkpoint/1,
+    db/2,
+    doc_fdi/3,
+    db_closing/2
+]).
+
+-include_lib("couch_scanner/include/couch_scanner_plugin.hrl").
+
+start(ScanId, #{}) ->
+    St = init_config(ScanId),
+    case should_run() of
+        true ->
+            ?INFO("Starting.", [], St),
+            {ok, St};
+        false ->
+            ?INFO("Not starting.", [], St),
+            skip
+    end.
+
+resume(ScanId, #{}) ->
+    St = init_config(ScanId),
+    case should_run() of
+        true ->
+            ?INFO("Resuming.", [], St),
+            {ok, St};
+        false ->
+            ?INFO("Not resuming.", [], St),
+            skip
+    end.
+
+complete(St) ->
+    ?INFO("Completed", [], St),
+    {ok, #{}}.
+
+checkpoint(_St) ->
+    {ok, #{}}.
+
+db(St, _DbName) ->
+    {ok, St}.
+
+doc_fdi(St, #full_doc_info{} = FDI, Db) when not is_map_key(Db, St) ->
+    %% cache TimeSeq for this db.
+    doc_fdi(St#{couch_db:name(Db) => couch_db:get_time_seq(Db)}, FDI, Db);
+doc_fdi(#{sid := ScanId} = St, #full_doc_info{deleted = true} = FDI, Db) ->
+    TimeSeq = maps:get(couch_db:name(Db), St),
+    TTL = 30 * 24 * 60 * 60,
+    SinceSeq = couch_time_seq:since(TimeSeq, couch_time_seq:timestamp() - TTL),
+    ?INFO("burp ~p.", [St], #{sid => ScanId}),
+    if
+        FDI#full_doc_info.update_seq =< SinceSeq ->
+            ?INFO("purging tombstone ~p in ~p.", [FDI#full_doc_info.id, Db], 
#{sid => ScanId}),
+            purge(Db, FDI);
+        true ->            
+            ok
+    end,
+    {ok, St};
+doc_fdi(St, #full_doc_info{}, _Db) ->
+    ?INFO("burp2 ~p.", [St]),
+    {stop, St}.
+
+db_closing(St, Db) ->
+    {ok, maps:remove(couch_db:name(Db), St)}.
+
+init_config(ScanId) ->
+    #{sid => ScanId}.
+
+should_run() ->
+    couch_scanner_util:on_first_node().
+
+purge(Db, #full_doc_info{} = FDI) ->
+    ok.

Reply via email to