From d2753fe117b299555987164a85f6800881fc805b Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Wed, 3 Dec 2025 12:08:37 +0000 Subject: [PATCH] ensure we decrement clients_requesting_changes ensure we decrement clients_requesting_changes even if the mochiweb process mediating the change request is killed by the client disconnect detector. --- src/chttpd/src/chttpd_db.erl | 7 ++-- src/couch/src/couch_changes_mon.erl | 47 +++++++++++++++++++++++++++ src/couch/src/couch_httpd_db.erl | 9 ++--- src/couch/src/couch_secondary_sup.erl | 3 +- 4 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 src/couch/src/couch_changes_mon.erl diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl index 5ef69f33f89..a878b0096b5 100644 --- a/src/chttpd/src/chttpd_db.erl +++ b/src/chttpd/src/chttpd_db.erl @@ -151,11 +151,8 @@ handle_changes_req1(#httpd{} = Req, Db) -> mochi = Req, threshold = Max }, - try - fabric:changes(Db, fun changes_callback/2, Acc0, ChangesArgs) - after - couch_stats:decrement_counter([couchdb, httpd, clients_requesting_changes]) - end; + couch_changes_mon:decrement_clients_requesting_changes_on_exit(), + fabric:changes(Db, fun changes_callback/2, Acc0, ChangesArgs); _ -> Msg = <<"Supported `feed` types: normal, continuous, live, longpoll, eventsource">>, throw({bad_request, Msg}) diff --git a/src/couch/src/couch_changes_mon.erl b/src/couch/src/couch_changes_mon.erl new file mode 100644 index 00000000000..39c1c5f6674 --- /dev/null +++ b/src/couch/src/couch_changes_mon.erl @@ -0,0 +1,47 @@ +% 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_changes_mon). + +-behaviour(gen_server). + +-export([decrement_clients_requesting_changes_on_exit/0]). + +-export([ + start_link/0, + init/1, + handle_call/3, + handle_cast/2, + handle_info/2 +]). + +decrement_clients_requesting_changes_on_exit() -> + gen_server:cast(?MODULE, {monitor_me, self()}). + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +init(_) -> + {ok, nil}. + +handle_call(_Msg, _From, State) -> + {reply, error, State}. + +handle_cast({monitor_me, Pid}, State) -> + monitor(process, Pid), + {noreply, State}. + +handle_info({'DOWN', _MonitorRef, process, _Pid, _Info}, State) -> + couch_stats:decrement_counter([couchdb, httpd, clients_requesting_changes]), + {noreply, State}; +handle_info(_Msg, State) -> + {noreply, State}. diff --git a/src/couch/src/couch_httpd_db.erl b/src/couch/src/couch_httpd_db.erl index 733991d8421..405be0bb12b 100644 --- a/src/couch/src/couch_httpd_db.erl +++ b/src/couch/src/couch_httpd_db.erl @@ -189,13 +189,8 @@ handle_changes_req1(Req, Db, ChangesArgs, ChangesFun) -> couch_stats:increment_counter( [couchdb, httpd, clients_requesting_changes] ), - try - WrapperFun(ChangesFun) - after - couch_stats:decrement_counter( - [couchdb, httpd, clients_requesting_changes] - ) - end. + couch_changes_mon:decrement_clients_requesting_changes_on_exit(), + WrapperFun(ChangesFun). handle_compact_req(#httpd{method = 'POST'} = Req, Db) -> case Req#httpd.path_parts of diff --git a/src/couch/src/couch_secondary_sup.erl b/src/couch/src/couch_secondary_sup.erl index 8fc3c9a13d7..d5a527a982a 100644 --- a/src/couch/src/couch_secondary_sup.erl +++ b/src/couch/src/couch_secondary_sup.erl @@ -27,7 +27,8 @@ init([]) -> {query_servers, {couch_proc_manager, start_link, []}}, {vhosts, {couch_httpd_vhost, start_link, []}}, {uuids, {couch_uuids, start, []}}, - {disk_manager, {couch_disk_monitor, start_link, []}} + {disk_manager, {couch_disk_monitor, start_link, []}}, + {couch_changes_mon, {couch_changes_mon, start_link, []}} ] ++ couch_index_servers(), MaybeHttp =