]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: stream: Add be_max_retries/cur_max_retries sample fetch functions
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 7 Jul 2026 08:36:45 +0000 (10:36 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 8 Jul 2026 06:52:07 +0000 (08:52 +0200)
These new samples can be used to get, resepectively, the backend value for
the maximum connection retries and the current value applied to the stream.
They could be used to know if a "set-retries" action was performed.

A dedicated reg-test was also added.

doc/configuration.txt
reg-tests/stream/set-retries.vtc [new file with mode: 0644]
src/backend.c
src/stream.c

index 26137459ee4741c6e81b1c40bb25c3b78730da0c..45d405145a9b902c404377a083be579b9fcb0443 100644 (file)
@@ -24325,6 +24325,7 @@ bc_srv_queue                                       integer
 be_id                                              integer
 be_name                                            string
 be_connect_timeout                                 integer
+be_max_retries                                     integer
 be_queue_timeout                                   integer
 be_server_timeout                                  integer
 be_tarpit_timeout                                  integer
@@ -24333,6 +24334,7 @@ bytes_in                                           integer
 bytes_out                                          integer
 cur_connect_timeout                                integer
 cur_client_timeout                                 integer
+cur_max_retries                                    integer
 cur_queue_timeout                                  integer
 cur_server_timeout                                 integer
 cur_tarpit_timeout                                 integer
@@ -24669,6 +24671,11 @@ be_connect_timeout : integer
   current backend. This timeout can be overwritten by a "set-timeout" rule. See
   also the "cur_connect_timeout".
 
+be_max_retries : integer
+  Returns the configuration value for the connection retries of the current
+  backend. This value can be overwritten by a "set-retries" rule. See also the
+  "cur_max_retries".
+
 be_name : string
   Returns a string containing the current backend's name. It can be used in
   frontends with responses to check which backend processed the request. If
@@ -24712,6 +24719,11 @@ cur_client_timeout : integer
   In the default case, this will be equal to fe_client_timeout unless a
   "set-timeout" rule has been applied. See also "fe_client_timeout".
 
+cur_max_retries : integer
+  Returns the currently applied connect retries for the stream.
+  In the default case, this will be equal to be_max_retries unless a
+  "set-retries" rule has been applied. See also "be_max_retries".
+
 cur_queue_timeout : integer
   Returns the currently applied queue timeout in millisecond for the stream.
   In the default case, this will be equal to be_queue_timeout unless a
diff --git a/reg-tests/stream/set-retries.vtc b/reg-tests/stream/set-retries.vtc
new file mode 100644 (file)
index 0000000..ddffaf2
--- /dev/null
@@ -0,0 +1,114 @@
+varnishtest "set-retries action test"
+
+feature ignore_unknown_macro
+
+server srv_h1 -repeat 6 {
+    rxreq
+    txresp -hdr "Connection: close"
+} -start
+
+
+haproxy hap -conf {
+    global
+    .if feature(THREAD)
+        thread-groups 1
+    .endif
+
+    defaults
+        timeout connect 5s
+        timeout client 5s
+        timeout server 5s
+       retries 3
+        log global
+
+    listen li1
+        mode http
+        bind "fd@${li1}"
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+        server srv_h1 ${srv_h1_addr}:${srv_h1_port}
+
+    listen li2
+        mode http
+        bind "fd@${li2}"
+        http-request set-retries 5
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+        server srv_h1 ${srv_h1_addr}:${srv_h1_port}
+
+    listen li3
+        mode http
+        bind "fd@${li3}"
+        http-request set-retries 5
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+       default_backend be1
+
+    listen li4
+        mode http
+        bind "fd@${li4}"
+        http-request set-retries 4
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+       default_backend be2
+
+    frontend fe5
+        mode http
+        bind "fd@${fe5}"
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+        default_backend be1
+
+    frontend fe6
+        mode http
+        bind "fd@${fe6}"
+        http-after-response set-header retries "%[be_max_retries] %[cur_max_retries]"
+        default_backend be2
+
+    backend be1
+       mode http
+       server srv_h1 ${srv_h1_addr}:${srv_h1_port}
+
+    backend be2
+       mode http
+       http-request set-retries 5
+       server srv_h1 ${srv_h1_addr}:${srv_h1_port}
+
+} -start
+
+client c1 -connect ${hap_li1_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 3"
+} -run
+
+client c2 -connect ${hap_li2_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 5"
+} -run
+
+client c3 -connect ${hap_li3_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 3"
+} -run
+
+client c4 -connect ${hap_li4_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 5"
+} -run
+
+client c5 -connect ${hap_fe5_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 3"
+} -run
+
+client c6 -connect ${hap_fe6_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.retries == "3 5"
+} -run
index d04466eea8aaf3361f51c0aea0b08304a9c18710..4001135ba2daae31ea2bfc93fdfb20c4d4ddfcc6 100644 (file)
@@ -3756,6 +3756,24 @@ smp_fetch_srv_uweight(const struct arg *args, struct sample *smp, const char *kw
        return 1;
 }
 
+static int
+smp_fetch_be_max_retries(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+       struct proxy *px = NULL;
+
+       if (smp->strm)
+               px = smp->strm->be;
+       else if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK)
+               px = __objt_check(smp->sess->origin)->proxy;
+       if (!px)
+               return 0;
+
+       smp->flags = SMP_F_VOL_TXN;
+       smp->data.type = SMP_T_SINT;
+       smp->data.u.sint = px->conn_retries;
+       return 1;
+}
+
 static int
 smp_fetch_be_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
 {
@@ -3929,6 +3947,7 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "be_id",             smp_fetch_be_id,             0,           NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "be_name",           smp_fetch_be_name,           0,           NULL, SMP_T_STR,  SMP_USE_BKEND, },
        { "be_connect_timeout",smp_fetch_be_connect_timeout,0,           NULL, SMP_T_SINT, SMP_USE_BKEND, },
+       { "be_max_retries",    smp_fetch_be_max_retries,    0,           NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "be_queue_timeout",  smp_fetch_be_queue_timeout,  0,           NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "be_server_timeout", smp_fetch_be_server_timeout, 0,           NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "be_sess_rate",      smp_fetch_be_sess_rate,      ARG1(1,BE),  NULL, SMP_T_SINT, SMP_USE_INTRN, },
index ccf0ea993d2562d62c5ee59f4c63d27c606be126..862f5576b948aabe69967c1a8f4160a2229a9542 100644 (file)
@@ -4420,6 +4420,17 @@ static struct action_kw_list stream_http_after_res_actions =  { ILH, {
 
 INITCALL1(STG_REGISTER, http_after_res_keywords_register, &stream_http_after_res_actions);
 
+static int smp_fetch_cur_max_retries(const struct arg *args, struct sample *smp, const char *km, void *private)
+{
+       smp->flags = SMP_F_VOL_TXN;
+       smp->data.type = SMP_T_SINT;
+       if (!smp->strm)
+               return 0;
+
+       smp->data.u.sint = smp->strm->max_retries;
+       return 1;
+}
+
 static int smp_fetch_cur_connect_timeout(const struct arg *args, struct sample *smp, const char *km, void *private)
 {
        smp->flags = SMP_F_VOL_TXN;
@@ -4687,6 +4698,7 @@ static int smp_fetch_redispatched(const struct arg *args, struct sample *smp, co
 static struct sample_fetch_kw_list smp_kws = {ILH, {
        { "cur_connect_timeout",smp_fetch_cur_connect_timeout,0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "cur_client_timeout", smp_fetch_cur_client_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND, },
+       { "cur_max_retries",    smp_fetch_cur_max_retries,    0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "cur_server_timeout", smp_fetch_cur_server_timeout, 0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "cur_queue_timeout",  smp_fetch_cur_queue_timeout,  0, NULL, SMP_T_SINT, SMP_USE_BKEND, },
        { "cur_tarpit_timeout", smp_fetch_cur_tarpit_timeout, 0, NULL, SMP_T_SINT, SMP_USE_FTEND | SMP_USE_BKEND, },