The directives enable cache updates in subrequests.
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_revalidate),
NULL },
+ { ngx_string("fastcgi_cache_background_update"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_background_update),
+ NULL },
+
#endif
{ ngx_string("fastcgi_temp_path"),
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
+ conf->upstream.cache_background_update = NGX_CONF_UNSET;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
+ ngx_conf_merge_value(conf->upstream.cache_background_update,
+ prev->upstream.cache_background_update, 0);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_convert_head),
NULL },
+ { ngx_string("proxy_cache_background_update"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_background_update),
+ NULL },
+
#endif
{ ngx_string("proxy_temp_path"),
conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
conf->upstream.cache_convert_head = NGX_CONF_UNSET;
+ conf->upstream.cache_background_update = NGX_CONF_UNSET;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
ngx_conf_merge_value(conf->upstream.cache_convert_head,
prev->upstream.cache_convert_head, 1);
+ ngx_conf_merge_value(conf->upstream.cache_background_update,
+ prev->upstream.cache_background_update, 0);
+
#endif
if (conf->method == NULL) {
offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_revalidate),
NULL },
+ { ngx_string("scgi_cache_background_update"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_background_update),
+ NULL },
+
#endif
{ ngx_string("scgi_temp_path"),
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
+ conf->upstream.cache_background_update = NGX_CONF_UNSET;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
+ ngx_conf_merge_value(conf->upstream.cache_background_update,
+ prev->upstream.cache_background_update, 0);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
NULL },
+ { ngx_string("uwsgi_cache_background_update"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update),
+ NULL },
+
#endif
{ ngx_string("uwsgi_temp_path"),
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
conf->upstream.cache_revalidate = NGX_CONF_UNSET;
+ conf->upstream.cache_background_update = NGX_CONF_UNSET;
#endif
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0);
+ ngx_conf_merge_value(conf->upstream.cache_background_update,
+ prev->upstream.cache_background_update, 0);
+
#endif
ngx_conf_merge_value(conf->upstream.pass_request_headers,
unsigned purged:1;
unsigned reading:1;
unsigned secondary:1;
+ unsigned background:1;
unsigned stale_updating:1;
unsigned stale_error:1;
*psr = sr;
+ if (flags & NGX_HTTP_SUBREQUEST_CLONE) {
+ sr->method = r->method;
+ sr->method_name = r->method_name;
+ sr->loc_conf = r->loc_conf;
+ sr->valid_location = r->valid_location;
+ sr->phase_handler = r->phase_handler;
+ sr->write_event_handler = ngx_http_core_run_phases;
+
+ ngx_http_update_location_config(sr);
+ }
+
return ngx_http_post_request(sr, NULL);
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0,
"http file cache cleanup");
- if (c->updating) {
+ if (c->updating && !c->background) {
ngx_log_error(NGX_LOG_ALERT, c->file.log, 0,
"stalled cache updating, error:%ui", c->error);
}
/* unused 1 */
#define NGX_HTTP_SUBREQUEST_IN_MEMORY 2
#define NGX_HTTP_SUBREQUEST_WAITED 4
-#define NGX_HTTP_LOG_UNSAFE 8
+#define NGX_HTTP_SUBREQUEST_CLONE 8
+
+#define NGX_HTTP_LOG_UNSAFE 1
#define NGX_HTTP_CONTINUE 100
#if (NGX_HTTP_CACHE)
unsigned cached:1;
+ unsigned cache_updater:1;
#endif
#if (NGX_HTTP_GZIP)
ngx_http_upstream_t *u, ngx_http_file_cache_t **cache);
static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
ngx_http_upstream_t *u);
+static ngx_int_t ngx_http_upstream_cache_background_update(
+ ngx_http_request_t *r, ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_cache_check_range(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
rc = NGX_DECLINED;
r->cached = 0;
}
+
+ if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) {
+ rc = NGX_ERROR;
+ }
}
if (rc != NGX_DECLINED) {
switch (rc) {
+ case NGX_HTTP_CACHE_STALE:
+
+ if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
+ || c->stale_updating) && !r->cache_updater
+ && u->conf->cache_background_update)
+ {
+ r->cache->background = 1;
+ u->cache_status = rc;
+ rc = NGX_OK;
+ }
+
+ break;
+
case NGX_HTTP_CACHE_UPDATING:
- if ((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
- || c->stale_updating)
+ if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
+ || c->stale_updating) && !r->cache_updater)
{
u->cache_status = rc;
rc = NGX_OK;
}
+static ngx_int_t
+ngx_http_upstream_cache_background_update(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
+{
+ ngx_http_request_t *sr;
+
+ if (!r->cached || !r->cache->background) {
+ return NGX_OK;
+ }
+
+ if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL,
+ NGX_HTTP_SUBREQUEST_CLONE)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ sr->header_only = 1;
+ sr->cache_updater = 1;
+
+ return NGX_OK;
+}
+
+
static ngx_int_t
ngx_http_upstream_cache_check_range(ngx_http_request_t *r,
ngx_http_upstream_t *u)
ngx_flag_t cache_revalidate;
ngx_flag_t cache_convert_head;
+ ngx_flag_t cache_background_update;
ngx_array_t *cache_valid;
ngx_array_t *cache_bypass;