Mailing List Archive

[master] e676f7793 purge: Use EXP_Reduce() instead of EXP_Rearm()
commit e676f77939e7dbde851ee3aa58dfd36505f2b7e8
Author: AlveElde <alve_elde@hotmail.com>
Date: Tue Mar 19 13:44:24 2024 +0100

purge: Use EXP_Reduce() instead of EXP_Rearm()

When a stale object is soft-purged, the time until the object expires
should not be reset, as repeated soft-purges could keep the object
around indefinitely.

diff --git a/bin/varnishd/cache/cache_hash.c b/bin/varnishd/cache/cache_hash.c
index 8627c7a95..32f9340c7 100644
--- a/bin/varnishd/cache/cache_hash.c
+++ b/bin/varnishd/cache/cache_hash.c
@@ -747,7 +747,7 @@ HSH_Purge(struct worker *wrk, struct objhead *oh, vtim_real ttl_now,
if (is_purge)
EXP_Remove(ocp[i], NULL);
else
- EXP_Rearm(ocp[i], ttl_now, ttl, grace, keep);
+ EXP_Reduce(ocp[i], ttl_now, ttl, grace, keep);
(void)HSH_DerefObjCore(wrk, &ocp[i], 0);
AZ(ocp[i]);
total++;
diff --git a/bin/varnishtest/tests/m00057.vtc b/bin/varnishtest/tests/m00057.vtc
new file mode 100644
index 000000000..8f9c67d1f
--- /dev/null
+++ b/bin/varnishtest/tests/m00057.vtc
@@ -0,0 +1,60 @@
+varnishtest "Softpurging a stale object"
+
+server s1 {
+ rxreq
+ txresp -hdr "version: 1"
+
+ rxreq
+ txresp -hdr "version: 2"
+} -start
+
+varnish v1 -vcl+backend {
+ import purge;
+
+ sub vcl_hit {
+ if (req.http.purge) {
+ set req.http.npurged = purge.soft();
+ return (synth(200));
+ }
+ }
+
+ sub vcl_backend_response {
+ set beresp.grace = 3s;
+ set beresp.keep = 10s;
+ }
+
+ sub vcl_synth {
+ set resp.http.npurged = req.http.npurged;
+ }
+} -start
+
+client c1 {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.http.version == "1"
+
+ # Softpurge the object
+ txreq -hdr "purge: yes"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Wait for half the grace period
+ delay 1.5
+
+ # Softpurge the object again, this should not reset the expiry timer
+ txreq -hdr "purge: yes"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Wait for the object to enter keep
+ delay 1.5
+
+ # A grace hit should not be possible now
+ txreq
+ rxresp
+ expect resp.http.version == "2"
+ expect resp.status == 200
+} -run
diff --git a/bin/varnishtest/tests/m00058.vtc b/bin/varnishtest/tests/m00058.vtc
new file mode 100644
index 000000000..e339764ae
--- /dev/null
+++ b/bin/varnishtest/tests/m00058.vtc
@@ -0,0 +1,86 @@
+varnishtest "Softpurging an object cannot increase grace or keep"
+
+server s1 {
+ rxreq
+ txresp -hdr "Last-Modified: Wed, 11 Sep 2013 13:36:55 GMT" -body "foo"
+
+ rxreq
+ expect req.http.if-modified-since == "Wed, 11 Sep 2013 13:36:55 GMT"
+ txresp -body "bar"
+} -start
+
+varnish v1 -arg "-p vsl_mask=+ExpKill" -vcl+backend {
+ import purge;
+ import std;
+
+ sub vcl_hit {
+ if (req.http.purge) {
+ set req.http.npurged = purge.soft(
+ grace = std.duration(req.http.grace, -1s),
+ keep = std.duration(req.http.keep, -1s));
+ return (synth(200));
+ }
+ }
+
+ sub vcl_backend_response {
+ set beresp.ttl = 1y;
+ set beresp.grace = 1y;
+ set beresp.keep = 1y;
+ }
+
+ sub vcl_synth {
+ set resp.http.npurged = req.http.npurged;
+ }
+} -start
+
+client c1 {
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.body == "foo"
+
+ # Reduce the objects grace
+ txreq -hdr "purge: yes" -hdr "grace: 10s"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Reduce the objects keep
+ txreq -hdr "purge: yes" -hdr "keep: 10s"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Reduce the objects grace and keep
+ txreq -hdr "purge: yes" -hdr "grace: 1s" -hdr "keep: 5s"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Increasing the objects grace is not possible
+ txreq -hdr "purge: yes" -hdr "grace: 15s"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Increasing the objects keep is not possible
+ txreq -hdr "purge: yes" -hdr "keep: 105"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Increasing the objects grace and keep is not possible
+ txreq -hdr "purge: yes" -hdr "grace: 15s" -hdr "keep: 15s"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.npurged == 1
+
+ # Wait for the obejct to enter keep
+ delay 1
+
+ # We don't get a grace hit, but the backend gets an IMS header
+ txreq
+ rxresp
+ expect resp.status == 200
+ expect resp.body == "bar"
+} -run
diff --git a/vmod/vmod_purge.vcc b/vmod/vmod_purge.vcc
index dc55a7f30..7fa7639da 100644
--- a/vmod/vmod_purge.vcc
+++ b/vmod/vmod_purge.vcc
@@ -98,12 +98,46 @@ $Restrict vcl_hit vcl_miss

$Function INT soft(DURATION ttl = 0, DURATION grace = -1, DURATION keep = -1)

-Sets the *ttl*, *grace* and *keep*.
-
-By default, *ttl* is set to 0 with *grace* and *keep* periods left
-untouched. Setting a negative value for *grace* or *keep* periods
-leaves them untouched. Setting all three parameters to ``0`` is
-equivalent to a hard purge. It returns the number of soft-purged objects.
+Sets the *ttl*, *grace* and *keep*. By default, *ttl* is set to ``0`` with
+*grace* and *keep* periods left untouched. Setting *grace* or *keep* to a
+negative value or to something higher than the objects current value leaves them
+untouched. Setting all three parameters to ``0`` is equivalent to a hard purge.
+Returns the number of soft-purged objects.
+
+A soft-purge can only decrease the lifetime of an object. Let's consider an
+object in cache created with *ttl*, *grace*, and *keep* of 60 seconds each:
+
+``purge.soft(ttl = 0s, grace = -1s, keep = -1s);``
+
+* If the object is **fresh**, the *ttl* is reduced to 0 seconds and the object
+ expires after 120 seconds.
+* If the object is **stale**, the expiry time is not changed.
+
+``purge.soft(ttl = 0s, grace = 10s, keep = 10s);``
+
+* If the object is **fresh**, the *ttl* is reduced to 0 seconds, *grace* and
+ *keep* are reduced to 10 seconds. The object expires after 20 seconds.
+* If the object has been **stale** for 5 seconds, *grace* is reduced to 5
+ seconds and *keep* is reduced to 10 seconds. The object expires after 15
+ seconds.
+* If the object has been **stale** for 15 seconds, *grace* is reduced to 0
+ seconds and *keep* is reduced to 5 seconds. The object expires after 5
+ seconds.
+* If the object has been **stale** for 20 seconds or more, the object
+ immediately expires.
+
+``purge.soft(ttl = 10s, grace = -1s, keep = -1s);``
+
+* If the object has been **fresh** for 5 seconds, the *ttl* is reduced to 10
+ seconds. The object expires after 130 seconds.
+* If the object has been **fresh** for 55 seconds, the *ttl* is not changed. The
+ object expires after 125 seconds.
+* If the object is **stale**, the expiry time is not changed.
+
+When the expiry time of an object is reduced due to a softpurge, an
+``EXP_Reduce`` entry is logged under the ``ExpKill`` VSL tag. If a softpurge
+does not reduce the expiry time of an object, an ``EXP_Unchanged`` entry is
+logged instead.

$Restrict vcl_hit vcl_miss
SEE ALSO
_______________________________________________
varnish-commit mailing list
varnish-commit@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit