# HG changeset patch # User Roman Arutyunyan # Date 1486728821 -10800 # Node ID 1aeaae6e944615c1adb5592f214dd63306416470 # Parent 9a9e136868694a5c13a37f71d6763d873bd520b8 Upstream: proxy_cache_background_update and friends. The directives enable cache updates in subrequests. diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -469,6 +469,13 @@ static ngx_command_t ngx_http_fastcgi_c 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"), @@ -2769,6 +2776,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con 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; @@ -3061,6 +3069,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf 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, diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -548,6 +548,13 @@ static ngx_command_t ngx_http_proxy_com 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"), @@ -2863,6 +2870,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ 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; @@ -3168,6 +3176,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t 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) { diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -319,6 +319,13 @@ static ngx_command_t ngx_http_scgi_comma 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"), @@ -1219,6 +1226,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t 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; @@ -1506,6 +1514,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t 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, diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -379,6 +379,13 @@ static ngx_command_t ngx_http_uwsgi_comm 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"), @@ -1425,6 +1432,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ 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; @@ -1720,6 +1728,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t 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, diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -116,6 +116,7 @@ struct ngx_http_cache_s { unsigned purged:1; unsigned reading:1; unsigned secondary:1; + unsigned background:1; unsigned stale_updating:1; unsigned stale_error:1; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2566,6 +2566,17 @@ ngx_http_subrequest(ngx_http_request_t * *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); } diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1688,7 +1688,7 @@ ngx_http_file_cache_cleanup(void *data) 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); } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -62,7 +62,9 @@ /* 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 @@ -481,6 +483,7 @@ struct ngx_http_request_s { #if (NGX_HTTP_CACHE) unsigned cached:1; + unsigned cache_updater:1; #endif #if (NGX_HTTP_GZIP) diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -17,6 +17,8 @@ static ngx_int_t ngx_http_upstream_cache 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, @@ -578,6 +580,10 @@ ngx_http_upstream_init_request(ngx_http_ rc = NGX_DECLINED; r->cached = 0; } + + if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { + rc = NGX_ERROR; + } } if (rc != NGX_DECLINED) { @@ -869,10 +875,23 @@ ngx_http_upstream_cache(ngx_http_request 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; @@ -1046,6 +1065,30 @@ ngx_http_upstream_cache_send(ngx_http_re 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) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -202,6 +202,7 @@ typedef struct { 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;