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

Commit da5e2ac

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 508306f commit da5e2ac

2 files changed

Lines changed: 101 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/b00092.vtc

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

0 commit comments

Comments
 (0)