Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.

Commit 47eeb93

Browse files
committed
expire: Force a cache MISS when req.ttl = 0s
This commit changes the undefined behavior of setting req.ttl = 0s. Setting req.ttl = 0s would previously cause req.ttl to have no effect, but this breaks with setting req.grace = 0s, which does have an effect. The new behavior of setting req.ttl = 0s is similar to setting req.hash_always_miss = true, the main difference is that req.ttl allows for request coalescing. Useful for short-lived non-private objects. This aligns the behavior of setting req.ttl = 0s with req.grace = 0s.
1 parent 5f67d3a commit 47eeb93

2 files changed

Lines changed: 93 additions & 1 deletion

File tree

bin/varnishd/cache/cache_expire.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ EXP_Ttl(const struct req *req, const struct objcore *oc)
7373
CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
7474

7575
r = oc->ttl;
76-
if (req != NULL && req->d_ttl > 0. && req->d_ttl < r)
76+
if (req != NULL && req->d_ttl >= 0. && req->d_ttl < r)
7777
r = req->d_ttl;
7878
return (oc->t_origin + r);
7979
}

bin/varnishtest/tests/b00083.vtc

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
varnishtest "req.ttl = 0s forces cache MISS with request coalescing"
2+
3+
barrier b1 cond 3 -cyclic
4+
5+
server s1 {
6+
rxreq
7+
txresp -nolen -hdr "Content-Length: 3" -hdr "version: 1"
8+
barrier b1 sync
9+
send "foo"
10+
11+
rxreq
12+
txresp -nolen -hdr "Content-Length: 3" -hdr "version: 2"
13+
barrier b1 sync
14+
send "bar"
15+
} -start
16+
17+
varnish v1 -vcl+backend {
18+
import std;
19+
20+
sub vcl_recv {
21+
if (req.http.ttl) {
22+
set req.ttl = std.duration(req.http.ttl, 0s);
23+
}
24+
}
25+
} -start
26+
27+
# c1 and c2 send a request and sync on the barrier only after having received
28+
# headers. This ensures that the two requests are coalesced.
29+
30+
client c1 {
31+
txreq -hdr "ttl: 0s"
32+
rxresphdrs
33+
expect resp.status == 200
34+
expect resp.http.version == "1"
35+
barrier b1 sync
36+
rxrespbody
37+
expect resp.body == "foo"
38+
} -start
39+
40+
client c2 {
41+
txreq -hdr "ttl: 0s"
42+
rxresphdrs
43+
expect resp.status == 200
44+
expect resp.http.version == "1"
45+
barrier b1 sync
46+
rxrespbody
47+
expect resp.body == "foo"
48+
} -start
49+
50+
client c1 -wait
51+
client c2 -wait
52+
53+
# c3 checks that a positive or unset req.ttl gets the cached object.
54+
55+
client c3 {
56+
txreq -hdr "ttl: 10s"
57+
rxresp
58+
expect resp.status == 200
59+
expect resp.http.version == "1"
60+
expect resp.body == "foo"
61+
62+
txreq
63+
rxresp
64+
expect resp.status == 200
65+
expect resp.http.version == "1"
66+
expect resp.body == "foo"
67+
} -run
68+
69+
# c4 and c5 force a cache MISS, where the two requests are again coalesced.
70+
71+
client c4 {
72+
txreq -hdr "ttl: 0s"
73+
rxresphdrs
74+
expect resp.status == 200
75+
expect resp.http.version == "2"
76+
barrier b1 sync
77+
rxrespbody
78+
expect resp.body == "bar"
79+
} -start
80+
81+
client c5 {
82+
txreq -hdr "ttl: 0s"
83+
rxresphdrs
84+
expect resp.status == 200
85+
expect resp.http.version == "2"
86+
barrier b1 sync
87+
rxrespbody
88+
expect resp.body == "bar"
89+
} -start
90+
91+
client c4 -wait
92+
client c5 -wait

0 commit comments

Comments
 (0)