Skip to content

Commit 19b6cda

Browse files
authored
fix: no tag cache writes index ready (#40)
1 parent beea11c commit 19b6cda

2 files changed

Lines changed: 66 additions & 25 deletions

File tree

bench/bench.pl

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use FindBin;
1010
use Getopt::Long qw(GetOptions);
1111
use HTTP::Request;
12-
use JSON::PP ();
1312
use LWP::UserAgent;
1413
use POSIX qw(setpgid strftime);
1514
use Time::HiRes qw(sleep);
@@ -41,6 +40,7 @@
4140

4241
my $duration = $options{quick} ? 15 : 60;
4342
my $index_probe_timeout_s = 15;
43+
my $index_settle_delay_s = 1;
4444
my $scenario_ready_timeout_s = 10;
4545
my $perl = $^X;
4646
my $nginx = '/opt/nginx/sbin/nginx';
@@ -307,15 +307,26 @@ sub run_scenario {
307307
warm_cache($scenario->{prefix}, $options{count}, $scenario);
308308
wait_for_scenario_ready($scenario, $stats_endpoint, $scenario_ready_timeout_s);
309309

310-
if (($scenario->{index_mode} || '') eq 'wildcard-index') {
310+
if (($scenario->{index_mode} || '') eq 'wildcard-index'
311+
&& $index_settle_delay_s > 0) {
311312
# Index metadata is written asynchronously; give it a brief settle
312313
# window before running assist preflight probes.
313-
sleep(1.0);
314+
log_info("Waiting ${index_settle_delay_s}s for wildcard index metadata to settle");
315+
sleep($index_settle_delay_s);
314316
}
315317

316318
$probe_report = ensure_index_probe_ready($scenario, $stats_endpoint,
317319
$index_probe_timeout_s);
318320

321+
if (($scenario->{index_mode} || '') eq 'wildcard-index') {
322+
log_info("Re-warming cache for $scenario->{name} after wildcard index preflight");
323+
warm_cache($scenario->{prefix}, $options{count}, $scenario);
324+
if ($index_settle_delay_s > 0) {
325+
log_info("Waiting ${index_settle_delay_s}s for wildcard index metadata to settle after re-warm");
326+
sleep($index_settle_delay_s);
327+
}
328+
}
329+
319330
log_info("Fetching baseline stats for $scenario->{name}");
320331
$before = fetch_stats($stats_endpoint);
321332

@@ -644,6 +655,7 @@ sub ensure_index_probe_ready {
644655
my $request;
645656
my $response;
646657
my $deadline;
658+
my $attempt_probe_prefix;
647659
my $attempts = 0;
648660
my $last_hits = 0;
649661

@@ -673,22 +685,24 @@ sub ensure_index_probe_ready {
673685
}
674686
} @vary_values;
675687
$purge_url = "http://127.0.0.1:$options{port}$scenario->{prefix}${probe_prefix}";
676-
677-
} else {
678-
@probe_requests = map {
679-
{
680-
url => "http://127.0.0.1:$options{port}$scenario->{prefix}${probe_prefix}$_",
681-
headers => [],
682-
}
683-
} 0 .. 9;
684-
$purge_url = "http://127.0.0.1:$options{port}$scenario->{prefix}${probe_prefix}*";
685688
}
686689

687690
log_info("Running $mode index preflight for $scenario->{name}");
688691

689692
while (hires_time() < $deadline) {
690693
$attempts++;
691694

695+
if ($mode eq 'wildcard-index') {
696+
$attempt_probe_prefix = $probe_prefix + $attempts - 1;
697+
@probe_requests = map {
698+
{
699+
url => "http://127.0.0.1:$options{port}$scenario->{prefix}${attempt_probe_prefix}$_",
700+
headers => [],
701+
}
702+
} 0 .. 9;
703+
$purge_url = "http://127.0.0.1:$options{port}$scenario->{prefix}${attempt_probe_prefix}*";
704+
}
705+
692706
for my $probe_request (@probe_requests) {
693707
$response = $ua->get($probe_request->{url},
694708
@{ $probe_request->{headers} });

src/ngx_cache_pilot_index_runtime.c

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,6 @@ ngx_http_cache_pilot_index_header_filter(ngx_http_request_t *r) {
126126
return NGX_ERROR;
127127
}
128128

129-
if (tags->nelts == 0) {
130-
goto done;
131-
}
132-
133129
ctx = ngx_http_get_module_ctx(r, ngx_http_cache_pilot_module);
134130
if (ctx == NULL) {
135131
ctx = ngx_pcalloc(r->pool, sizeof(*ctx));
@@ -154,9 +150,10 @@ ngx_http_cache_pilot_index_header_filter(ngx_http_request_t *r) {
154150
* Log phase handler: commit the SHM index entry for a freshly written cache
155151
* file. Runs after the response is sent; the SHM write is in-memory and fast.
156152
*
157-
* We only proceed if the request context was stashed in the header filter,
158-
* which happens only for cacheable upstream responses - so we naturally skip
159-
* cache hits, purge requests, and any request that did not write a cache file.
153+
* The header filter normally stashes the request context for cacheable upstream
154+
* responses. Some no-tag cache writes can reach log phase without that
155+
* context, so the log handler can lazily recover the index zone and empty tag
156+
* set from the request before writing metadata.
160157
*
161158
* If the upstream response turned out to be non-cacheable despite the initial
162159
* header verdict (e.g. a downstream filter cleared cacheable), we silently
@@ -165,20 +162,50 @@ ngx_http_cache_pilot_index_header_filter(ngx_http_request_t *r) {
165162
static ngx_int_t
166163
ngx_http_cache_pilot_index_log_handler(ngx_http_request_t *r) {
167164
#if (NGX_LINUX)
165+
ngx_http_cache_pilot_loc_conf_t *cplcf;
168166
ngx_http_cache_pilot_request_ctx_t *ctx;
169167
ngx_http_cache_index_store_t *writer;
168+
ngx_http_cache_index_zone_t *zone;
169+
ngx_array_t *tags;
170170
ngx_str_t cache_key;
171171
ngx_str_t *key_parts;
172+
ngx_str_t zone_name;
172173
size_t key_len;
173174
ngx_uint_t i;
174175

175176
ctx = ngx_http_get_module_ctx(r, ngx_http_cache_pilot_module);
176-
if (ctx == NULL || ctx->index_tags == NULL || ctx->index_tags->nelts == 0) {
177+
if (r->cache == NULL || r->cache->file.name.len == 0) {
177178
return NGX_OK;
178179
}
179180

180-
if (r->cache == NULL || r->cache->file.name.len == 0) {
181-
return NGX_OK;
181+
tags = NULL;
182+
ngx_str_null(&zone_name);
183+
184+
if (ctx != NULL && ctx->index_tags != NULL) {
185+
tags = ctx->index_tags;
186+
zone_name = ctx->index_zone_name;
187+
} else {
188+
if (r->upstream != NULL
189+
&& r->upstream->cache_status == NGX_HTTP_CACHE_HIT) {
190+
return NGX_OK;
191+
}
192+
193+
cplcf = ngx_http_get_module_loc_conf(r, ngx_http_cache_pilot_module);
194+
if (!ngx_http_cache_index_location_enabled(cplcf)) {
195+
return NGX_OK;
196+
}
197+
198+
zone = ngx_http_cache_index_lookup_zone(r->cache->file_cache);
199+
if (zone == NULL) {
200+
return NGX_OK;
201+
}
202+
203+
if (ngx_http_cache_pilot_index_response_headers(r, cplcf, &tags)
204+
!= NGX_OK) {
205+
return NGX_OK;
206+
}
207+
208+
zone_name = zone->zone_name;
182209
}
183210

184211
writer = ngx_http_cache_index_store_writer();
@@ -209,11 +236,11 @@ ngx_http_cache_pilot_index_log_handler(ngx_http_request_t *r) {
209236

210237
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
211238
"cache_tag index update zone:\"%V\" path:\"%V\"",
212-
&ctx->index_zone_name, &r->cache->file.name);
239+
&zone_name, &r->cache->file.name);
213240

214-
if (ngx_http_cache_index_store_upsert_file_meta(writer, &ctx->index_zone_name,
241+
if (ngx_http_cache_index_store_upsert_file_meta(writer, &zone_name,
215242
&r->cache->file.name, &cache_key,
216-
ngx_time(), 0, ctx->index_tags, r->connection->log) != NGX_OK) {
243+
ngx_time(), 0, tags, r->connection->log) != NGX_OK) {
217244
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
218245
"cache_tag index update failed for \"%V\"",
219246
&r->cache->file.name);

0 commit comments

Comments
 (0)